12

在 haskell 工作,发现奇怪的行为,将其剥离为裸露的骨头

这个作品

a :: Bool
a = case True of
    True -> True
    False -> False

但是当我尝试

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

我明白了

ghci>:l test.hs
[1 of 1] Compiling Main             ( test.hs, interpreted )

test.hs:16:14: parse error on input ‘->’
Failed, modules loaded: none.

所以我尝试

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

这有效。

什么?为什么?在这种情况下,为什么我需要额外的缩进?我在这方面找不到任何东西,可能是因为这些关键字在日常语言中是如此简短和常见。是否有一些规范可以解释这种行为?

4

2 回答 2

14

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.

于 2015-10-08T08:42:54.737 回答
9
于 2015-10-08T00:15:39.407 回答