繁体   English   中英

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

[英]Has the ability to use let statements in do blocks been removed in GHC 8.6.5?

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

main = do { a <- getLine ; let b = "Hello " ++ a ; putStrLn b }

但是,我收到此错误:

<interactive>:1:63: error: parse error on input `}'

在以前版本的Haskell / GHC中,我记得这很好用 - 它甚至明确地说,在do块中,你不需要in关键字。 然而,让这个工作的唯一方法似乎是:

main = do { a <- getLine ; let b = "Hello " ++ a in putStrLn b }

这不会产生这个错误。

这被删除了吗? 如果是这样,我是否需要在let in表达式中使用第二个do块?

let是一个类似do的布局关键字,既可以作为do块中的语句,也可以作为let ... in ...表达式,因为它引入了一个绑定 这个:

main = do
  a <- getLine
  let b = "Hello " ++ a
  putStrLn b

Desugars to this:

main = do {
  a <- getLine;
  let {
    b = "Hello " ++ a;
  };
  putStrLn b;
};

虽然你写的东西等同于:

main = do {
  a <- getLine;
  let {
    b = "Hello " ++ a;
    putStrLn b
  };
};

所以GHC自然会期待一些其他的东西 - 一个模式或者= -after putStrLn b ,因为你可以用一个名为b的参数定义一个名为putStrLn的本地函数。 解决方案是在let语句中使用显式括号:

main = do { a <- getLine; let { b = "Hello " ++ a }; putStrLn b }

或者在GHCi中使用多行模式,使用:{ command,以:}命令终止:

> :{
| main = do
|   a <- getLine
|   let b = "Hello " ++ a
|   putStrLn b
| :}
>

或者使用:set +m ,并以空行结束:

> :set +m
| main = do
|   a <- getLine
|   let b = "Hello " ++ a
|   putStrLn b
|
>

其次是:unset +m返回单行模式。

问题在于它将你的putStrLn b解析为let声明,因此它基本上将它解析为:

do { a <- getLine; let { b = "Hello " ++ a ; putStrLn b } }

因此,它在putStrLn部分中寻找a = ,您将在其中定义putStrLn函数。 因此,解析器具有“想法”,即您正在定义函数,而不是调用函数。

实际上,我们可以写例如:

Prelude> let a = 3; f b = b + 1
Prelude> f a
4

所以这里我们在同一行中声明了两个变量。

您可以使用大括号来明确let的范围仅为b ,例如:

do { a <- getLine; let { b = "Hello " ++ a }; putStrLn b }

let的优先级是由于语法,在第3章: Haskell'10报告中的 表达式定义。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM