let语句中的case语句需要什么缩进?

时间:2015-10-08 00:12:24

标签: haskell indentation do-notation

在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'

这很有效。

什么?为什么?在这种情况下,为什么我需要额外的缩进?我无法找到任何相关信息,可能是因为这些关键字在日常用语中非常简短。是否有一些规范可以解释这种行为?

2 个答案:

答案 0 :(得分:10)

基本缩进规则实际上非常简单:

  • 在开始一个块的关键字(whereletdocase .. of之后)记下下一个词开头的列(可能在下一行)
  • 线条缩进与块中的新条目完全一致
  • 缩进的行多于上一个条目
  • 缩进的线条小于该行的那一行
  • 在嵌套块中,首先将规则应用于最外面的块

棘手的例子:

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"

在你的情况下,

let b' = case True of
    True -> True
    False -> False

我们有两个嵌套块,一个用于let,另一个用于case..oflet块使用b'列。 case..of块尝试重用相同的列,但我们需要首先将规则应用于最外层的块。因此True -> ...行实际上是let块的新条目。这会触发解析错误。

答案 1 :(得分:7)

我没有从规范中得到准确的措辞,但是Wikibook page非常清楚地解释了这个问题。

它的工作原理很简单:支持通过单个let-group绑定多个变量,例如:

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

您的True -> …False -> …被错误地解释为要绑定的其他变量。