在GHC 8.6.5中是否已删除在do块中使用let语句的功能?

sch*_*ine 2 syntax monads haskell let do-notation

我在中输入了一些代码ghci,类似于以下代码:

main = do { a <- getLine ; let b = "Hello " ++ a ; putStrLn b }
Run Code Online (Sandbox Code Playgroud)

但是,我收到此错误:

<interactive>:1:63: error: parse error on input `}'
Run Code Online (Sandbox Code Playgroud)

在Haskell / GHC的早期版本中,我记得这种方法工作得很好-甚至明确指出,在do块中,您不需要in关键字。但是,使它起作用的唯一方法似乎是:

main = do { a <- getLine ; let b = "Hello " ++ a in putStrLn b }
Run Code Online (Sandbox Code Playgroud)

不会产生此错误。

这个被删除了吗?如果是这样,我是否需要dolet in表达式中添加第二个块?

Jon*_*rdy 7

let是一个布局像关键字do,同时作为在一个语句do块和在let... in...表达式,因为它引入一个的绑定。这个:

main = do
  a <- getLine
  let b = "Hello " ++ a
  putStrLn b
Run Code Online (Sandbox Code Playgroud)

糖到此:

main = do {
  a <- getLine;
  let {
    b = "Hello " ++ a;
  };
  putStrLn b;
};
Run Code Online (Sandbox Code Playgroud)

而您编写的内容与此等效:

main = do {
  a <- getLine;
  let {
    b = "Hello " ++ a;
    putStrLn b
  };
};
Run Code Online (Sandbox Code Playgroud)

因此,GHC很自然地期待其他东西-模式或=-之后putStrLn b,因为您可以定义一个名为的局部函数putStrLn,而该函数的名称为b。解决方案是在let语句中使用显式括号:

main = do { a <- getLine; let { b = "Hello " ++ a }; putStrLn b }
Run Code Online (Sandbox Code Playgroud)

或通过以下:{命令在GHCi中使用多行模式,并以以下命令终止:}

> :{
| main = do
|   a <- getLine
|   let b = "Hello " ++ a
|   putStrLn b
| :}
>
Run Code Online (Sandbox Code Playgroud)

或以:set +m,并以空行终止:

> :set +m
| main = do
|   a <- getLine
|   let b = "Hello " ++ a
|   putStrLn b
|
>
Run Code Online (Sandbox Code Playgroud)

随后:unset +m返回单行模式。