Reading through Bartosz Milewski's piece at fpcomplete where he writes, "In Haskell you never assign to a variable, instead you bind a name to a value."
Could someone explain to me what this means, as well as the practical ramifications of this in the functional programming world?
In some sense, the only real difference is that variables in imperative languages can change whereas bound names in functional languages can't. But I think it's important to understand the higher-level semantic distinction between the two and how we think about them differently.
In imperative languages, a variable is a thing on its own which happens to include a value. They're often compared to boxes that contain something. The contents of a box can change and, semantically, the box has an identity of its own.
Haskell names, on the other hand, are just labels for a value. You can use one or the other completely interchangeably. Crucially, they can't change.
Compare binding in Haskell to function names in languages like Java¹. These can't change either, and you don't think of them on their own; they're just names for the method they're attached to.
Here's a contrived example of the difference: imagine a function f
that closes over an imperative variable x
:
var x = 7;
function foo() {
console.log(x);
}
Effectively, x
is just a name for 7
... until x
changes. What you've closed over is the variable x
, not its value 7
, so if it changes so will the behavior of foo
.
In Haskell, on the other hand, if you bind 7
to the name x
and close over it, that's the same as just closing over 7
.
let x = 7 in \ () -> x
does the same thing as
\ () -> 7
(which, itself, doesn't do anything more than just 7
by itself, ignoring strictness issues).
¹ ignoring reflection and similar shenanigans
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With