HASKELL ---在GHCI的"do"语法中使用"let"

Raf*_*zyk 1 syntax haskell let ghci

我知道这有效:

do name <- getLine; let nameTag = "Hello, my name is " ++ name in putStrLn nameTag 
Run Code Online (Sandbox Code Playgroud)

加载到GHCI时,这段代码也是如此:

hey = do 
    name <- getLine
    let nameTag = "Hello, my name is " ++ name
    putStrLn nameTag
Run Code Online (Sandbox Code Playgroud)

但这不起作用:

do name <- getLine; let nameTag = "Hello, my name is " ++ name; putStrLn nameTag 
Run Code Online (Sandbox Code Playgroud)

给出以下错误消息:

<interactive>:142:82:
  parse error (possibly incorrect indentation or mismatched brackets)
Run Code Online (Sandbox Code Playgroud)

为什么不起作用?我可以让它运作吗?如果是,那怎么样?

Bri*_*nna 5

是的,您可以在let绑定周围使用大括号来消除解析的歧义:

do name <- getLine; let { nameTag = "Hello, my name is " ++ name }; putStrLn nameTag
Run Code Online (Sandbox Code Playgroud)


chi*_*chi 5

为了补充 McKenna 的回答,错误可以解释如下:比较这两行

do name <- getLine; let name1 = "One"; putStrLn name1
do name <- getLine; let name1 = "One"; name2 = "Two"; putStrLn name1
Run Code Online (Sandbox Code Playgroud)

人类读者可以看到他们实际上是指

do { name <- getLine; let { name1 = "One" } ; putStrLn name1 }
do { name <- getLine; let { name1 = "One"; name2 = "Two" }; putStrLn name1 }
Run Code Online (Sandbox Code Playgroud)

但解析器并不那么聪明。当 Haskell 解析器看到公共代码部分时

do name <- getLine; let name1 = "One";
                                  -- ^ --
Run Code Online (Sandbox Code Playgroud)

它必须决定最后一个是;属于do级别(如上面的第一种情况),还是属于let级别(第二种情况)。事实证明,它选择了 ,但let后来失败了。