What indentation is required for a case statement within a let statement?
Solution 1:
The basic indentation rules are actually quite simple:
- after the keywords which start a block (
where
,let
,do
,case .. of
) note down the column where the next word starts (which might be in the next line) - lines indented exactly as that are new entries in the block
- lines indented more than that continue the previous entry
- a line indented less than that ends the block right before that line
- in nested blocks, apply the rules to the outermost block, first
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.
Solution 2:
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.