Search code examples
haskellcompiler-errorsparse-error

Compiler error for Haskell program not understood


I'm working on a large Haskell program, so I'm only including the code that seems relevant here to make the problem clearer. Please comment if I should include more.

When I compile, I get only one error message: "parse error (possibly incorrect indentation or mismatched brackets)"

Here is some code with no errors (printStmt) and a very similar section (VarDeclStmt) with the error directed at the line reading, "expr >>= \s ->". I don't see why one would be fine and the other would cause a problem. In what way are they different?

printStmt = 
            keyword "print" >>
            expr >>= \e ->
            symbol ";" >>
            return (Print e)

varDeclStmt = do
              keyword "var" >>
              expr >>= \s -> --ERROR
              symbol "=" >>
              expr >>= \e ->
              return (VarDecl s e) 

Solution

  • This is an indentation issue. The block

    varDeclStmt = do
                  keyword "var" >>
                  expr >>= \s -> --ERROR
                  symbol "=" >>
                  expr >>= \e ->
                  return (VarDecl s e) 
    

    parses as

    varDeclStmt = do
                  { keyword "var" >>
                  ; expr >>= \s -> --ERROR
                  ; symbol "=" >>
                  ; expr >>= \e ->
                  ; return (VarDecl s e) 
                  }
    

    which is nonsense, since the first entry keyword "var" >> is not valid.

    Note that indenting the whole block further (or less) does not change how it is parsed.

    The easiest fix is to remove do completely, so that the text below that is not parsed as a block, hence it is not split into separate entries, but parsed as if it were on a single line.

    Otherwise, you can switch to proper do notation

    varDeclStmt = do
                  keyword "var"
                  s <- expr
                  symbol "="
                  e <- expr
                  return (VarDecl s e) 
    

    or (worst solution), make the do block a single-entry one, making the block indented more than the first line, as follos

    varDeclStmt = do
                  keyword "var" >>
                    expr >>= \s ->
                    symbol "=" >>
                    expr >>= \e ->
                    return (VarDecl s e) 
    

    The above solution is silly, though, since the purpose of do is splitting the block into entries, and the indentation is made so that there is only one entry. So, we use two things to counteract each other.