如何在 Haskell 中正确使用 monadic 表达式而不会出现解析错误?
How to properly use monadic expressions in Haskell without getting parse errors?
我是 运行 GHC 版本 7.8.3 Windows 7.
好的,这不是花哨的代码片段。我只是不想在这里成为菜鸟,而是以一种隐约类似于副作用语言结构的方式编译一些东西。
我有以下代码:
main =
do {
let x = [0..10];
print x
}
I've learned here,关键字 do 是花哨的单子表达式的花哨语法糖。当我尝试编译它时,出现以下错误:
main.hs:4:1: parse error on input 'print'
而且我在 this other question 中了解到 Haskell 中的标签是邪恶的,所以我试图省略它们:
main =
do {
let x = [0..10];
print x
}
而且我失败得很惨,因为解析错误仍然存在。
I've also learned here,那个 print 是花哨等价物的语法糖:
main =
do {
let x = [0..10];
putStrLn $ show x
}
但后来我得到了这个错误:
main.hs:4:9: parse error on input 'putStrLn'
试图面对我的绝望,我试图省略 let 关键字,after reading this answer:
main =
do {
x = [0..10];
print x
}
然后我得到:
main.hs:4:1: parse error on input '='
在最后一次无用的尝试中,我什至试图省略“;”像这样:
main =
do {
let x = [0..10]
print x
}
得到:
main.hs:4:1: parse error on input 'print'
所以,
如何 在 Haskell 中正确使用 monadic 表达式而不出现解析错误?有希望吗?
main = do let x = [0..10]
print x
适合我
也是
main = do { let x = [0..10]
in print x }
我认为您正在尝试混合使用一些不同的语法选项。
我正想说,没有有用的信息,
main = do
let x = [0..10]
print x
为我工作,但我现在要去阅读大括号内的 in
。
顺便说一句,我发现 http://echo.rsmw.net/n00bfaq.html 对于阅读 identation/formatting 非常方便。
我花了一段时间才看到这里到底发生了什么:
main =
do {
let x = [0..10];
print x
}
上面看起来好像我们有一个包含两个语句的 do
,这非常好。当然,当缩进隐式插入大括号和分号时,使用显式大括号和分号是不常见的做法。但它们不应该受到伤害...为什么上面的解析失败?
真正的问题是 let
打开了一个新块! let
块没有大括号,因此适用缩进规则。该块以定义 x = [0..10]
开头。然后找到一个分号,它保证后面有另一个定义,例如
let x = [0..10] ; y = ...
甚至
let x = [0..10] ;
y = ... -- must be indented as the x above, or more indented
然而,在分号之后我们发现 print
,它甚至比 x
缩进得更少。根据缩进规则,这相当于插入大括号:
main =
do {
let { x = [0..10]; }
print x
}
但是上面没有解析。错误消息不涉及隐式插入的大括号(这会非常混乱!),但仅涉及下一行(不幸的是,在这种情况下几乎同样令人困惑)。
代码可以通过例如修复为 let
:
提供显式大括号
main = do { let { x = [0..10] };
print x }
以上,缩进完全无关紧要:您可以添加换行符 and/or 空格而不影响解析(例如 Java、C 等)。或者,我们可以移动下面的分号:
main = do { let x = [0..10]
; print x }
上面的分号在下一行并且比 x
缩进更少,隐含地插入了一个 }
来关闭 let
块。这里缩进很重要,因为 let
使用缩进规则。如果我们缩进更多的分号,我们可能会导致我们之前发现的相同的解析错误。
当然,最惯用的选择是对整个代码使用缩进规则:
main = do let x = [0..10]
print x
我是 运行 GHC 版本 7.8.3 Windows 7.
好的,这不是花哨的代码片段。我只是不想在这里成为菜鸟,而是以一种隐约类似于副作用语言结构的方式编译一些东西。
我有以下代码:
main =
do {
let x = [0..10];
print x
}
I've learned here,关键字 do 是花哨的单子表达式的花哨语法糖。当我尝试编译它时,出现以下错误:
main.hs:4:1: parse error on input 'print'
而且我在 this other question 中了解到 Haskell 中的标签是邪恶的,所以我试图省略它们:
main =
do {
let x = [0..10];
print x
}
而且我失败得很惨,因为解析错误仍然存在。
I've also learned here,那个 print 是花哨等价物的语法糖:
main =
do {
let x = [0..10];
putStrLn $ show x
}
但后来我得到了这个错误:
main.hs:4:9: parse error on input 'putStrLn'
试图面对我的绝望,我试图省略 let 关键字,after reading this answer:
main =
do {
x = [0..10];
print x
}
然后我得到:
main.hs:4:1: parse error on input '='
在最后一次无用的尝试中,我什至试图省略“;”像这样:
main =
do {
let x = [0..10]
print x
}
得到:
main.hs:4:1: parse error on input 'print'
所以,
如何 在 Haskell 中正确使用 monadic 表达式而不出现解析错误?有希望吗?
main = do let x = [0..10]
print x
适合我
也是
main = do { let x = [0..10]
in print x }
我认为您正在尝试混合使用一些不同的语法选项。
我正想说,没有有用的信息,
main = do
let x = [0..10]
print x
为我工作,但我现在要去阅读大括号内的 in
。
顺便说一句,我发现 http://echo.rsmw.net/n00bfaq.html 对于阅读 identation/formatting 非常方便。
我花了一段时间才看到这里到底发生了什么:
main =
do {
let x = [0..10];
print x
}
上面看起来好像我们有一个包含两个语句的 do
,这非常好。当然,当缩进隐式插入大括号和分号时,使用显式大括号和分号是不常见的做法。但它们不应该受到伤害...为什么上面的解析失败?
真正的问题是 let
打开了一个新块! let
块没有大括号,因此适用缩进规则。该块以定义 x = [0..10]
开头。然后找到一个分号,它保证后面有另一个定义,例如
let x = [0..10] ; y = ...
甚至
let x = [0..10] ;
y = ... -- must be indented as the x above, or more indented
然而,在分号之后我们发现 print
,它甚至比 x
缩进得更少。根据缩进规则,这相当于插入大括号:
main =
do {
let { x = [0..10]; }
print x
}
但是上面没有解析。错误消息不涉及隐式插入的大括号(这会非常混乱!),但仅涉及下一行(不幸的是,在这种情况下几乎同样令人困惑)。
代码可以通过例如修复为 let
:
main = do { let { x = [0..10] };
print x }
以上,缩进完全无关紧要:您可以添加换行符 and/or 空格而不影响解析(例如 Java、C 等)。或者,我们可以移动下面的分号:
main = do { let x = [0..10]
; print x }
上面的分号在下一行并且比 x
缩进更少,隐含地插入了一个 }
来关闭 let
块。这里缩进很重要,因为 let
使用缩进规则。如果我们缩进更多的分号,我们可能会导致我们之前发现的相同的解析错误。
当然,最惯用的选择是对整个代码使用缩进规则:
main = do let x = [0..10]
print x