Reputation: 4346
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
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
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