【问题标题】:Has the ability to use let statements in do blocks been removed in GHC 8.6.5?GHC 8.6.5 中是否删除了在 do 块中使用 let 语句的功能?
【发布时间】:2019-10-20 17:47:19
【问题描述】:

我在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 块?

【问题讨论】:

  • main = do { a &lt;- getLine ; let { b = "Hello " ++ a} ; putStrLn b } 工作正常。
  • 如果你不放大括号,我认为它会被解析为do { a &lt;- getLine ; let {b = "Hello " ++ a ; putStrLn b} }。毕竟,do { a &lt;- getLine ; let {b = "Hello " ++ a ; putStrLn b = ()} ; print 3 } 将是合法代码。

标签: haskell syntax monads let do-notation


【解决方案1】:

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

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

脱糖:

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

而你写的就是这样的:

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

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

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

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

> :{
| 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 返回单行模式。

【讨论】:

    【解决方案2】:

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

    do { a &lt;- getLine; let <b>{ b = "Hello " ++ a ; putStrLn b }</b> }

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

    确实,我们可以这样写:

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

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

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

    do { a &lt;- getLine; let <b>{ b = "Hello " ++ a }</b>; putStrLn b }

    let 的优先级取决于 Chapter 3: Expressions in the Haskell'10 report 中定义的语法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-10
      • 2018-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多