【问题标题】:let vs regular assignment in GHCi让与 GHCi 中的常规分配
【发布时间】:2017-03-23 23:42:07
【问题描述】:

有什么区别

f x = x + 1

let f x = x + 1

当输入 GHCi 时? IIUC,有一条特殊规则,let 没有 in 内部 GHCi 有效地适用于解释器的整个范围。但是如果let 的存在没有任何区别,那么这条规则的意义何在?

编辑:使用 GHCi 8.0.2 版。

【问题讨论】:

  • 哪个版本的 GHCi?我的不接受 f x = x + 1 作为输入(解析错误)。
  • @Mephy 这是 GHC 8 中的新功能。
  • 据我了解,必须使用let 在 GHCi 中绑定名称是其实现方式的影响。你可以想象你正在向 IO monad 中的“do-block”输入命令。
  • @Erik 我不是她,这就是它的实际实现方式(我相信您不是直接在 IO do 块中输入语句,而是在 GHCi 的代码中有一个 IO 操作正在解释您的声明)。但是,语法基于 do 块语法当然是故意的。

标签: haskell


【解决方案1】:

不,没有区别。

过去,ghci 本质上是一个开放式 IO do 块。但是无法以这种语法形式定义新类型,并且需要为每个定义编写let,这被视为烦人的限制,经常妨碍日常交互使用,因此 ghci 的语法慢慢变得越来越多允许的。但这只是语法上的改变——没什么深度。

但是,有一点需要注意:如果你想开始一个区块,你必须明确地这样做。例如,

> f [] = 3
> f (x:xs) = 4

等价于

> let f [] = 3
> let f (x:xs) = 4

而不是

> :{
| let f [] = 3
|     f (x:xs) = 4
| :}

因此将是f 定义,它会遮盖旧定义,并且仅在非空列表中定义,而您可能打算为单个f 提供两个等式。使用自动阻止模式(:set +m),ghci 可以注意到let 启动了一个阻止,并在您输入let 时自动给您后者,因此:

> let f [] = 3
|     f (x:xs) = 4
|

它不会对短格式(非let)定义执行此操作。

【讨论】:

    【解决方案2】:

    虽然这个问题是几个月前提出的,但当我最近开始学习 Haskell 时,我确实注意到了一些不同。

    > :set -Wall
    > a = 2
    > let a = 3
    

    导致关于name shadowing-Wname-shadowing)的警告,而

    > :set -Wall
    > a = 2
    > a = 3
    

    没有。似乎警告只检查明确编写的let 语句。

    【讨论】:

      【解决方案3】:

      另一个区别:

      λ> x = 1 :: Int
      λ> :sprint x
      x = _
      λ> let x = 1 :: Int
      λ> :sprint x
      x = 1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-11-18
        • 1970-01-01
        • 2018-12-22
        • 1970-01-01
        • 2023-03-09
        • 2010-10-10
        • 2019-05-30
        • 1970-01-01
        相关资源
        最近更新 更多