如何在Haskell中正确使用monadic表达式而不会出现解析错误?

Eri*_*ans 5 monads haskell

我在Windows 7上运行GHC版本7.8.3.

好吧,这不是关于花哨的代码片段.我只是想在这里不是一个菜鸟,实际上用一种模糊地类似于副作用语言结构的方式编译.

我有以下代码:

main = 
    do {
    let x = [0..10];
    print x
}
Run Code Online (Sandbox Code Playgroud)

我在这里学到,关键字do对于花哨的monadic表达式来说是一种花哨的语法糖.当我尝试编译它时,我收到以下错误:

main.hs:4:1: parse error on input 'print'
Run Code Online (Sandbox Code Playgroud)

我在其他问题中已经了解到,Haskell中的标签是邪恶的,所以我试图省略它们:

main = 
    do {
let x = [0..10];
print x
}
Run Code Online (Sandbox Code Playgroud)

而且我失败了,因为解析错误仍然存​​在.

我也在这里学到,印刷品是花式等价物的语法糖:

main = 
    do {
    let x = [0..10];
    putStrLn $ show x 
}
Run Code Online (Sandbox Code Playgroud)

但后来我得到了这个错误:

main.hs:4:9: parse error on input 'putStrLn'
Run Code Online (Sandbox Code Playgroud)

试着面对我的绝望,我试着在阅读这个答案之后省略了let关键字:

main = 
    do {
    x = [0..10];
    print x 
}
Run Code Online (Sandbox Code Playgroud)

然后我得到:

main.hs:4:1: parse error on input '='
Run Code Online (Sandbox Code Playgroud)

在最后的无用尝试中,我甚至试图省略';' 像这样:

main = 
    do {
    let x = [0..10]
    print x 
}
Run Code Online (Sandbox Code Playgroud)

得到了:

main.hs:4:1: parse error on input 'print'
Run Code Online (Sandbox Code Playgroud)

所以,

如何在Haskell中正确使用monadic表达式而不会出现解析错误?有什么希望吗?

chi*_*chi 15

我花了一段时间才看到实际发生的事情:

main = 
    do {
    let x = [0..10];
    print x
}
Run Code Online (Sandbox Code Playgroud)

上面看起来好像我们有do两个语句,这是完全正常的.当然,当缩进隐式插入它们时,使用显式括号和分号并不常见.但他们不应该受伤...为什么上面的解析失败?

真正的问题是let打开一个新的块!该let块没有大括号,因此缩进规则适用.该块以定义开头x = [0..10].然后找到一个分号,它承诺另一个定义如下

let x = [0..10] ; y = ...
Run Code Online (Sandbox Code Playgroud)

甚至

let x = [0..10] ;
      y = ...      -- must be indented as the x above, or more indented
Run Code Online (Sandbox Code Playgroud)

但是,在我们发现分号之后print,它甚至缩进了x.根据缩进规则,这相当于插入括号,如:

main = 
    do {
    let { x = [0..10]; }
    print x
}
Run Code Online (Sandbox Code Playgroud)

但上面没有解析.错误消息不是指隐式插入的大括号(这会非常令人困惑!),但仅限于下一行(不幸的是,在这种情况下几乎令人困惑).

代码可以通过例如提供显式括号来修复let:

main = do { let { x = [0..10] };
            print x }
Run Code Online (Sandbox Code Playgroud)

在上面,缩进完全不相关:您可以添加换行符和/或空格而不影响解析(例如,如Java,C等).或者,我们可以移动下面的分号:

main = do { let x = [0..10]
          ; print x }
Run Code Online (Sandbox Code Playgroud)

上面的分号位于下一行,并且缩进的次数少于x隐式插入}关闭let块的分号.这里缩进很重要,因为let使用了缩进规则.如果我们更多地缩进分号,我们可能会导致前面发现的相同解析错误.

当然,最惯用的选择是对整个代码使用缩进规则:

main = do let x = [0..10]
          print x
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,我对Haskell很新(这就是我浏览SO问题的原因),这有助于填补空白. (2认同)

Chr*_*ris 5

我正要说,没有任何有用的信息

main =  do 
    let x = [0..10]
    print x
Run Code Online (Sandbox Code Playgroud)

正在为我工​​作,但我现在正在阅读有关in括号内的信息.

稍微一点,我发现http://echo.rsmw.net/n00bfaq.html非常方便阅读有关身份/格式的内容.


Jay*_*nek 4

main = do let x = [0..10]
          print x
Run Code Online (Sandbox Code Playgroud)

为我工作

也是如此

main = do { let x = [0..10]
            in print x }
Run Code Online (Sandbox Code Playgroud)

我认为您正在尝试混合一些不同的语法选项。