问题
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?
回答1:
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.
回答2:
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.
来源:https://stackoverflow.com/questions/33004521/what-indentation-is-required-for-a-case-statement-within-a-let-statement