gaa*_*kam 6 haskell let switch-statement
我对Haskell的解析规则感到困惑。
这很漂亮:
n = 5
m = 6
b = case (n, m) of
(5, 6) -> True
_ -> False
main = print b
Run Code Online (Sandbox Code Playgroud)
让我们把它复杂化得很小,让我们let在混合物中添加一个:
b =
let res = case (n, m) of
(5, 6) -> True
_ -> False
in not res
Run Code Online (Sandbox Code Playgroud)
(注意,为了简便起见,我省略的定义n,m并main从现在开始,他们进行相同的,我只是改变b)
糟糕,这里的问题:
wtf.hs:5:5: error: parse error on input ‘(’
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
我不知道,也许那是我没有得到的某种奇怪的缩进规则。好的,让我们用括号括起来:
b =
let res = case (n, m) of {
(5, 6) -> True
_ -> False }
in not res
Run Code Online (Sandbox Code Playgroud)
还没有?!
wtf.hs:6:7: error: parse error on input ‘->’
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
我很困惑。我不知道该怎么办。为什么不行呢?让我们在这里添加一个明确的分号,即使这确实是一个盲目的镜头,即使我不明白为什么在这里需要它,因为毕竟AFAIK,换行符(在此存在)应该使分号变得多余:
b =
let res = case (n, m) of {
(5, 6) -> True;
_ -> False }
in not res
Run Code Online (Sandbox Code Playgroud)
终于可以了!
...不知道,也许问题就出在let和case是在同一行。作为我自己研究的最后尝试,让我们尝试一下:
b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res
Run Code Online (Sandbox Code Playgroud)
但是,由于我不知道的原因,这是行不通的:
wtf.hs:5:5: error:
parse error (possibly incorrect indentation or mismatched brackets)
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)
说真的,我在这里很困惑。为什么在这里需要使用括号和分号?(是吗?可以将代码格式化为不需要它们的方式吗?)
我没有到达Haskell的哪个晦涩的解析规则?
M. *_*osi 11
非正式地说,括号和分号的插入方式如下。只要在where,let,do或of关键字后省略左括号,布局(或“越位”)规则即会生效。发生这种情况时,将记住下一个词素的缩进(无论是否在新行上),并插入省略的大括号(词素前面的空白可能包含注释)。对于每个后续行,如果它仅包含空格或缩进更多,则前一项继续(不插入任何内容);如果缩进量相同,则开始新的项目(插入分号);如果缩进较少,则布局列表结束(插入了大括号)...
...此外,这些规则还允许:
Run Code Online (Sandbox Code Playgroud)f x = let a = 1; b = 2 g y = exp2 in exp1
该示例实际上显示了如何在Haskell中处理缩进,基本上,不是由关键字来确定事物的缩进程度,而是它之后的第一个标识符(或其他词素),因此对于
b = case (n, m) of
(5, 6) -> True
_ -> False
Run Code Online (Sandbox Code Playgroud)
这很好,因为第二行和第三行的缩进比b第一行的缩进更多,另一方面,
b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res
Run Code Online (Sandbox Code Playgroud)
本质上被解析为
b =
let { res =
} case (n, m) of
{ (5, 6) -> True
; _ -> False
} in not res
Run Code Online (Sandbox Code Playgroud)
这是因为case缩进不超过res,所以它不是其定义的一部分。
这就是为什么编译器抱怨解析错误(它期望之后有一个词素,=但什么也没得到case,因为它不符合let ... in ...语法,所以它也没有期望那里)。
相反,你应该写
b =
let res =
case (n, m) of
(5, 6) -> True
_ -> False
in not res
Run Code Online (Sandbox Code Playgroud)
要么
b =
let res = case (n, m) of
(5, 6) -> True
_ -> False
in not res
Run Code Online (Sandbox Code Playgroud)
两者都将按您期望的方式进行解析。