在Haskell中,为什么GHCi cmd行允许我更改变量的值,所以从文本文件加载时不允许这样做

plu*_*uke 1 haskell ghci

我可以在GHCi中执行以下操作,我知道在Haskell中不可能做到这一点:

Prelude> myPi = 3.14
Prelude> myPi = 4
Prelude> myPi
4
Run Code Online (Sandbox Code Playgroud)

但是如果我把它放在文件中,就会给我一个错误

-- main.hs
myPi = 3.14
myPi = 4
Run Code Online (Sandbox Code Playgroud)
Prelude> :l main.hs
main.hs:2:1: error:
    Multiple declarations of ‘myPi’
    Declared at: main.hs:1:1
                 main.hs:2:1
Run Code Online (Sandbox Code Playgroud)

GHCi在做什么,以允许我“重新声明”变量。有办法阻止这种情况发生吗?

lef*_*out 8

下面是这表明GHCI不会话不会改变的价值,而是引入了具有相同名称的新变量:

Prelude> let myPi = 3.14
Prelude> let f x = x + myPi
Prelude> let myPi = 4
Prelude> f 0
3.14
Run Code Online (Sandbox Code Playgroud)


Wil*_*sem 6

我可以在GHCi中执行以下操作,我知道在Haskell中不可能

Prelude> myPi = 3.14
Prelude> myPi = 4
Prelude> myPi
Run Code Online (Sandbox Code Playgroud)

ghci你里面基本上是在“隐式”工作do。并且解释器将let为其添加隐式。

因此,您写了相当于:

main = do
    let myPi = 3.14
    let myPi = 4
    print myPi
Run Code Online (Sandbox Code Playgroud)

如果我们对do符号进行减糖,则可以得到:

main = let myPi = 3.14 in (let myPi = 4 in print myPi)
Run Code Online (Sandbox Code Playgroud)

我们在这里所做的是构造两个不同的变量,它们恰好具有相同的名称。let定义一个范围,因此在您的中print myPi,它接受具有最接近范围的变量,因此第二个变量。

但是在内在之外let … in …,仍有一个myPi有价值的变量3.14。所以,你也不会改变的价值myPi

例如,如果我们写:

main = do
    let myPi = 3.14
    let myPi = 4 in print myPi
    print myPi
Run Code Online (Sandbox Code Playgroud)

它将首先4(从内部myPi)打印,然后3.14(从外部myPi)打印。