Reputation: 427
Someone told me Haskell does not have variables but bindings. Now what ever that means, I always wondered what the difference is when writing these bindings, like so:
x = 5
and
let x = 5
What is the difference here?
And a followup question: Am I even creating variables by doing this? If x is not a variable, what is it?
Upvotes: 9
Views: 859
Reputation: 30736
Haskell has variables, but we say they are bound rather than assigned. These are extremely similar notions, but they differ in whether they support multiple assignment - Haskell does not.
do let x = 1
let x = 2
print x -- prints "2"
When we say it does not, what we mean is that all variables are bound statically. This means that any time there's a reference to a variable, you can look back up through the code and find the one binding that it refers to.
Take, for example, Python, which does have multiple assignment.
def f(a):
x = 1 # first assignment
x = 2 # second assignment
for i in a:
x = i # third assignment
print x
print x
In the above example, there are three places where x
is assigned. When we refer to x
on the last line, we could be getting the 2
from the second assignment, or we could be getting one of the values from a
from the assignment in the loop. Whether the third assignment took place depends on whether a
was empty or not.
So let's look at similar code in Haskell:
f a = do let x = 1 -- first binding
let x = 2 -- second binding
for_ a $ \i -> do let x = i -- third binding
print x
print x
The final line of this output will always be "2", because at that point in the code, the second binding is the innermost binding that x
received in that scope. If we were to introduce another closer binding, then we could change that:
f a = do let x = 1 -- first binding
let x = 2 -- second binding
for_ a $ \i -> do let x = i -- third binding
print x
let x = head a -- fourth binding
print x
But what we can never do is introduce ambiguity about which binding something refers to.
Upvotes: 6
Reputation: 213228
The only real difference is where they occur.
-- At top (file) level or in "where" blocks, omit "let".
x = 5
f1 y = x + y
where
x = 5
-- Inside expressions or do-blocks, "let" is required.
f2 y = let x = 5
in x + y
f3 y = do someAction
let x = 5
return (x + y)
In all cases, x
is a variable. However, you cannot change (mutate) the value of the variable.
In the GHCi prompt, it seems like you change the value of a variable, but you cannot. You can only create new variables with the same name, the old variables still exist.
Prelude> let x = 3 Prelude> let f y = x + y Prelude> let x = 10 Prelude> f 1 4
If you had really changed the value of x
, then f 1
would be 11.
Upvotes: 15