pluke
pluke

Reputation: 4346

In Haskell why does the GHCi cmd line allow me to change the value of a variable, which isn't allowed when loading from a text file

I can do the following in GHCi, which I understand shouldn't be possible in Haskell:

Prelude> myPi = 3.14
Prelude> myPi = 4
Prelude> myPi
4

But if I put this in a file it gives me an error

-- main.hs
myPi = 3.14
myPi = 4
Prelude> :l main.hs
main.hs:2:1: error:
    Multiple declarations of ‘myPi’
    Declared at: main.hs:1:1
                 main.hs:2:1

What is GHCi doing to allow me to 'redeclare' variables. Is there a way of stopping this happening?

Upvotes: 2

Views: 336

Answers (2)

leftaroundabout
leftaroundabout

Reputation: 120711

Here's a session which demonstrates that GHCi does not change the value, but rather introduces a new variable with the same name:

Prelude> let myPi = 3.14
Prelude> let f x = x + myPi
Prelude> let myPi = 4
Prelude> f 0
3.14

Upvotes: 9

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476594

I can do the following in GHCi, which I understand shouldn't be possible in Haskell

Prelude> myPi = 3.14
Prelude> myPi = 4
Prelude> myPi

In ghci you basically are working in an "implicit" do. And the interpreter will add an implicit let to it.

You thus wrote the equivalent of:

main = do
    let myPi = 3.14
    let myPi = 4
    print myPi

If we desugar the do notation, we thus obtain:

main = let myPi = 3.14 in (let myPi = 4 in print myPi)

What we here did was constructing two different variables, that happen to have the same name. let defines a scope, and thus in your print myPi, it takes the variables that has the closest scope, so the second variable.

But outside the inner let … in …, there is still a myPi variable with value 3.14. So you did not change the value of myPi.

If we for example write:

main = do
    let myPi = 3.14
    let myPi = 4 in print myPi
    print myPi

It will first print 4 (from the inner myPi) and then 3.14 (from the outer myPi).

Upvotes: 8

Related Questions