[Haskell-cafe] Expanding do notation
Chris Kuklewicz
haskell at list.mightyreason.com
Sat Jan 7 14:23:40 EST 2006
Mmmm...now I had to go look it up.
David F. Place wrote:
> Hi Chris,
>
> Yes, this is just what I need to understand. Could you point me to a
> description of this? I couldn't find any discussion of it in the
> reference document. Thanks.
>
> Cheers, David
>
> On Jan 7, 2006, at 12:25 PM, Chris Kuklewicz wrote:
>
>> the mind-bending-thing I had to learn with Haskell is that the "let p ="
>> creates source code *shorthand*.
>
This is the first time I have tried to explain this. So it will not
help much...
The mantra is : Bindings are not variables
The best, official thing to read is section 3.12 of the Haskell98 Report:
http://www.haskell.org/onlinereport/exps.html#sect3.12
It shows that "let p = foo
q = bar
in ..."
is translated to
"let (~p,~q) = (foo,bar) in ..."
which is translated to
"case (foo,bar) of
~(~p, ~q) -> ..."
Assuming it does not refer to iteself, otherwise it becomes
"let (~p,~q) = fix (\ ~(~p,~q) -> (foo,bar) ) in ... "
which is translated to
"case fix (\ ~(~p,~q) -> (foo,bar) ) of
~(~p, ~q) -> ..."
At which point you are in section "3.13 Case Expressions"
So "let p = permutation [1..n]" merely pattern matches the bound name
"p" to the value that "permutations [1..n]" lazily evaluates to.
In Scheme/Lisp the let would allocate a specific cell "p" that would
point to the strictly evaluated result of "permutations [1..n]".
This Haskell pattern binding is the key to being referentially
transparent. It means there is no difference between "p" and
"permutations [1..n]". Allocating a memory cell for "p" would be an
observable difference, thus Haskell does no allocation.
This also means you can do this:
let a = 1
b = 2
c = 3
d = a+b+c
in a*b*c*d
without it having to allocate all those variables, because they are
shorthand, NOT VARIABLES. All bindings are constant, so the compiler
can substitute / inline them and never specifically allocate
intermediate stoage, thus "a,b,c,d" are not allocated.
This lets you break up a big function into many small expressions with
sensible names, and perhaps reuse the pieces.
Thus "map/foldl/filter/..."
--
Chris
More information about the Haskell-Cafe
mailing list