Reputation:
I'm confused by Haskell's parsing rules.
This works beautifuly:
n = 5
m = 6
b = case (n, m) of
(5, 6) -> True
_ -> False
main = print b
Let's complicate it only a teeny tiny bit, let's add a let
to the mixture:
b =
let res = case (n, m) of
(5, 6) -> True
_ -> False
in not res
(Note, for brevity I'm omitting definitions of n
, m
and main
from now on; they carry on the same, I'm only changing b
)
Oops, problems here:
wtf.hs:5:5: error: parse error on input ‘(’
Failed, modules loaded: none.
I don't know, maybe that's some kind of a weird indentation rule that I'm not getting. Fine, let's put explicit brackets:
b =
let res = case (n, m) of {
(5, 6) -> True
_ -> False }
in not res
Still not?!
wtf.hs:6:7: error: parse error on input ‘->’
Failed, modules loaded: none.
I'm totally confused. I don't know what to do. Why won't this work?? Let's add an explicit semicolon here, even though this is honestly a blind shot and even though I don't understand why would it be needed here, because after all, AFAIK, a newline (which is present here) should make semicolons redundant:
b =
let res = case (n, m) of {
(5, 6) -> True;
_ -> False }
in not res
And this finally works!
... don't know, maybe the problem lies in let
and case
being on the same line. As a last attempt to research this myself, let's try this:
b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res
This however won't work for reasons that are mysterious to me:
wtf.hs:5:5: error:
parse error (possibly incorrect indentation or mismatched brackets)
Failed, modules loaded: none.
Seriously, I'm confused here. Why are explicit brackets and semicolons needed here? (And are they? Can the code be formatted in such a way that they are not needed?)
Which obscure parsing rule of Haskell I'm not getting here?
Upvotes: 6
Views: 724
Reputation: 4646
Informally stated, the braces and semicolons are inserted as follows. The layout (or “off-side”) rule takes effect whenever the open brace is omitted after the keyword where, let, do, or of. When this happens, the indentation of the next lexeme (whether or not on a new line) is remembered and the omitted open brace is inserted (the whitespace preceding the lexeme may include comments). For each subsequent line, if it contains only whitespace or is indented more, then the previous item is continued (nothing is inserted); if it is indented the same amount, then a new item begins (a semicolon is inserted); and if it is indented less, then the layout list ends (a close brace is inserted)...
...Also, these rules permit:
f x = let a = 1; b = 2 g y = exp2 in exp1
This example actually shows how you are expected to treat the indentation in Haskell, basically it's not the keywords that determine how indented something is, rather it is the first identifier (or other lexeme) following them, so in the case of
b = case (n, m) of
(5, 6) -> True
_ -> False
This is fine since the 2nd and 3rd lines are indented more than the b
in the first line, on the other hand, the following
b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res
Is essentially parsed as
b =
let { res =
} case (n, m) of
{ (5, 6) -> True
; _ -> False
} in not res
And this is because case
isn't indented more than res
, so it's not part of its definition.
and it's why the compiler complains about a parse error (it expects a lexeme after =
but gets nothing, it also doesn't expect the case
there since it doesn't fit the let ... in ...
syntax).
Instead you should write
b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res
or
b =
let res = case (n, m) of
(5, 6) -> True
_ -> False
in not res
Both of which will be parsed as you expect.
Upvotes: 11