It might just be easiest for me to explain than to find another resource:

"let" and "where" are both ways of creating local variables in a function. They 
serve similar purposes, and in most cases, it's your choice of which one to 
use. (Comparing to C++, the choice of let vs. where is not too far from the 
choice between while(…) { … } and do { … } while(…). There are differences, but 
they're more a matter of style than anything else.) Further complicating this, 
in Haskell, is that there are two forms of "let": one that appears with "do" 
notation and one that appears independent of "do". So, we will tackle the three 
forms ("let … in", "where", and "let" with "do") separately:

Normal "let":
In a function (which does not use "do"), you can use "let" to make local 
variables. The word "in" separates the local variable declaration from the part 
of your function where you want to use that variable. Loosely translating from 
Haskell to C++:

Haskell:
> let foo = bar in baz

C++:
> /* insert correct type here */ foo = bar;
> baz

In both languages, the variable foo is available while executing baz.

Haskell allows multiple variable declarations lumped together in one "let", for 
convenience. These variables do not have to have the same type.

> let foo1 = bar1
>     foo2 = bar2
> in
> baz

In this last example, the "let" declares both foo1 and foo2, and you can use 
these variables in baz (and in bar1 and bar2, if you really want). Note that 
here is a place where indentation matters -- foo2 has the same indentation 
level as foo1. The "in" can appear on the same line as the last variable 
declaration or not, at your choosing.

This form of "let" (the one outside of "do") *always* needs an "in".


"where":
At the end of a function clause definition (a function clause is one branch of 
a function that does argument pattern-matching), you can insert a "where" 
section to declare local variables in that clause.

> some_function x =
>   do_cool_thing a b
>   where
>     a = blah x
>     b = something_long_and_complicated

Here, a and b are available in the body of the function (and throughout the 
"where" clause). This would be equivalent to

> some_function x =
>   let a = blah x
>       b = something_long_and_complicated
>   in do_cool_thing a b

It's best to use descriptive variable names with "where", because it can be 
hard to read code that uses "where" and poor variable names, as the definitions 
of the variables comes after their use.

"where" can also be used in other contexts, but I don't want to over-complicate 
things here -- this is the most common place for "where".


"let" in "do":

Using "do" notation, you can use "let" much like a normal "let", but this "let" 
has no "in". The variables declared by the "let" scope over the remainder of 
the "do" block.

> some_fun x = do
>   c <- something_monadic x
>   let a = pure_function c
>   another_monadic_thing c a

Here, the variable "a" is available in the last line. Note that there is no 
"in". This form of "let" can also, declare multiple new variables, just like 
the other one. It still does not have "in".

I hope this all helps!
Richard

On Apr 1, 2013, at 11:16 AM, A Smith wrote:

> Hi
> I think I've mastered much of  functional programming with Haskell, or at 
> least I can write programs which process as desired.
> However the existence of the "let" statement  evades me  apart from a quick 
> way to define a function. Then there is the "in" and "where" parts. Its been 
> suggested its to do with scope and is obvious. I think I need to understand 
> it in a C/C++/Perl style of code to have a Eureka moment   when it will be 
> obvious.
> Can someone refer me to something  which will assist me ?
> 
> Andrew _______________________________________________
> Haskell-Cafe mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/haskell-cafe

_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to