gpt4 book ai didi

haskell - let 表达式中的 case 表达式是否需要大括号和分号?

转载 作者:行者123 更新时间:2023-12-02 12:14:36 25 4
gpt4 key购买 nike

我对 Haskell 的解析规则感到困惑。

这工作得很漂亮:

n = 5
m = 6
b = case (n, m) of
(5, 6) -> True
_ -> False

main = print b

让我们把它复杂化一点点,让我们添加一个 let 到混合物中:

b =
let res = case (n, m) of
(5, 6) -> True
_ -> False
in not res

(注意,为了简洁起见,从现在开始我将省略 nmmain 的定义;它们具有相同的功能,我只是更改 b)

哎呀,这里有问题:

wtf.hs:5:5: error: parse error on input ‘(’
Failed, modules loaded: none.

我不知道,也许这是我没有得到的某种奇怪的缩进规则。好吧,让我们加上明确的括号:

b =
let res = case (n, m) of {
(5, 6) -> True
_ -> False }
in not res

还没有?!

wtf.hs:6:7: error: parse error on input ‘->’
Failed, modules loaded: none.

我完全糊涂了。我不知道该怎么办。为什么这不起作用?让我们在这里添加一个明确的分号,尽管这实际上是一个盲注,尽管我不明白为什么这里需要它,因为毕竟,据我所知,换行符(此处存在)应该使分号变得多余:

b =
let res = case (n, m) of {
(5, 6) -> True;
_ -> False }
in not res

这终于起作用了!

...不知道,也许问题在于 letcase 在同一行。作为我自己研究这个问题的最后一次尝试,让我们尝试一下:

b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res

然而,由于对我来说很神秘的原因,这不起作用:

wtf.hs:5:5: error:
parse error (possibly incorrect indentation or mismatched brackets)
Failed, modules loaded: none.

说实话,我很困惑。为什么这里需要明确的括号和分号? (它们是吗?可以将代码格式化为不需要它们吗?)

我没有在这里了解 Haskell 的哪些晦涩的解析规则?

最佳答案

From the Haskell 2010 Report :

Informally stated, the braces and semicolons are inserted as follows. The layout (or “off-side”) rule takes effect whenever the open brace is omitted after the keyword where, let, do, or of. When this happens, the indentation of the next lexeme (whether or not on a new line) is remembered and the omitted open brace is inserted (the whitespace preceding the lexeme may include comments). For each subsequent line, if it contains only whitespace or is indented more, then the previous item is continued (nothing is inserted); if it is indented the same amount, then a new item begins (a semicolon is inserted); and if it is indented less, then the layout list ends (a close brace is inserted)...

...Also, these rules permit:

f x = let a = 1; b = 2  
g y = exp2
in exp1

这个例子实际上展示了你应该如何处理 Haskell 中的缩进,基本上不是关键字决定某些东西的缩进,而是它们后面的第一个标识符(或其他词位) ,所以在

的情况下
b = case (n, m) of
(5, 6) -> True
_ -> False

这很好,因为第二行和第三行比第一行中的 b 缩进更多,另一方面,以下

b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res

本质上被解析为

b =
let { res =
} case (n, m) of
{ (5, 6) -> True
; _ -> False
} in not res

这是因为 case 的缩进不超过 res,因此它不是其定义的一部分。
这就是为什么编译器提示解析错误(它期望 = 之后有一个词素,但什么也没得到,它也不期望那里的 case 因为它不适合let ... in ... 语法)。

相反,你应该写

b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res

b =
let res = case (n, m) of
(5, 6) -> True
_ -> False
in not res

两者都会按照您的预期进行解析。

关于haskell - let 表达式中的 case 表达式是否需要大括号和分号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55278358/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com