Working in haskell, found odd behavior, stripped it down to bare bones
This Works
a :: Bool
a = case True of
True -> True
False -> False
But when I try
b :: IO Bool
b = do
let b' = case True of
True -> True
False -> False
return b'
I get
ghci>:l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
test.hs:16:14: parse error on input ‘->’
Failed, modules loaded: none.
So I try
c :: IO Bool
c = do
let c' = case True of
True -> True
False -> False
return c'
And this works.
What? Why? Why do I need an extra indent in this case? I can't find anything on this, probably because these keyword are so short and common in everyday language. Is there some spec that explains this behavior?
The basic indentation rules are actually quite simple:
where
,let
,do
,case .. of
) note down the column where the next word starts (which might be in the next line)Tricky example:
1 + case x of
A -> 45 -- note where "A" starts
B -> 10 -- same indentation: another case branch
+ 2 -- more indented, so it's "10+2"
+ 10 -- less indented, so it's "1+(case ...)+10"
In your case,
let b' = case True of
True -> True
False -> False
we have two nested blocks, one for let
and one for case..of
. The let
blocks uses the column of b'
. The case..of
block tries to reuse the same column, but we need to apply the rules the the outermost block, first. So the True -> ...
line is actually a new entry of the let
block. This triggers a parsing error.
I don't have the exact wording from the spec, but this Wikibook page explains the issue quite clearly.
The reason why it works like this is simple: to support binding multiple variables via a single let-group, such as:
c = do
let c' = …
d = …
e = …
return c'
Your True -> …
and False -> …
are mistakenly interpreted as additional variables to be bound.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With