What indentation is required for a case statement in a let statement?

Work in haskell, found odd behavior, split it into bare bones

It 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'm trying

 c :: IO Bool c = do let c' = case True of True -> True False -> False return c' 

And it works.

What? What for? Why do I need extra indentation in this case? I can’t find anything about this, probably because these keywords are so short and common in everyday language. Is there any specification that explains this behavior?

+5
source share
2 answers

I do not have the exact wording from the specification, but this Wikibook page explains the problem quite clearly.

The reason this works is simple: to support binding of several variables with a single let-group, for example:

 c = do let c' = … d = … e = … return c' 

Your True -> … and False -> … mistakenly interpreted as additional variables to be bound.

+7
source

The basic indentation rules are actually quite simple:

  • after the keywords that launched the block ( where , let , do , case .. of ), mark the column in which the next word begins (which may be on the next line)
  • indented lines are exactly like new entries in a block
  • indented lines longer than the previous entry
  • indented line is less than the end of the block right in front of this line
  • in nested blocks, apply rules to the most remote block, first

Difficult example:

 1 + case x of A -> 45 -- note where "A" starts B -> 10 -- same indentation: another case branch + 2 -- more indented, so it "10+2" + 10 -- less indented, so it "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 . let blocks use column b' . The case..of block tries to reuse the same column, but you must first apply the rules to the most remote block. Thus, the line True -> ... represents a new record of the let block. This causes a parsing error.

+7
source

Source: https://habr.com/ru/post/1233208/


All Articles