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

use*_*282 9 haskell indentation do-notation

在哈斯克尔工作,发现奇怪的行为,将其剥离为裸骨

这个作品

a :: Bool
a = case True of
    True -> True
    False -> False
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试

b :: IO Bool
b = do
    let b' = case True of
        True -> True
        False -> False
    return b'
Run Code Online (Sandbox Code Playgroud)

我明白了

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

test.hs:16:14: parse error on input ‘->’
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

所以我试试

c :: IO Bool
c = do
    let c' = case True of
            True -> True
            False -> False
    return c'
Run Code Online (Sandbox Code Playgroud)

这很有效.

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

chi*_*chi 11

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

  • 其中启动区块的关键字后(where,let,do,case .. 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"
Run Code Online (Sandbox Code Playgroud)

在你的情况下,

let b' = case True of
    True -> True
    False -> False
Run Code Online (Sandbox Code Playgroud)

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

  • 作为 Haskell 的初学者,我认为缩进规则并不简单,但是,这是我遇到的最好的解释。我已经为这个答案添加了书签,并希望继续回到它:) (2认同)

Ruf*_*ind 7

我没有规范中的确切措辞,但是这个Wikibook页面非常清楚地解释了这个问题.

它之所以如此工作很简单:支持通过单个let-group绑定多个变量,例如:

c = do
    let c' = …
        d  = …
        e  = …
    return c'
Run Code Online (Sandbox Code Playgroud)

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

  • 另一方面,`让Just f = ...`是一个完全有效的声明. (4认同)
  • "数据构造函数的大写是为了消除这样的含糊之处"在这种情况下你不能依赖它.如果你的模式匹配如下:`case ... of {x - > ...; _ - > ......; }?在这种情况下,`x`和`_`都是有效的变量名.(举个例子,我知道,但仍然.) (2认同)