# let/where

**John Hughes
**
rjmh@cs.chalmers.se

*Wed, 19 Sep 2001 22:34:11 +0200 (MET DST)*

The point of where is that it scopes over guards and multiple equations as
well as right hand sides.
f x | xsquared < 1000 = xsquared
| otherwise = 0
where xsquared = x*x
For the same reason, it has to be restricted to appear at the "top level" of a
right hand side. Of course, we also need a construct to bind local variables
inside an expression -- hence let, which therefore cannot scope over guards.
Two kinds of scope, two binding constructions.
We could have got away with one, if we had thrown out guards and relied just
on if-then-else to test conditions instead. But guards are very expressive:
some programs would have been a lot harder to write without them. Typical
examples are when we just want to pick out one case in the first equation of a
function, before lots of pattern matching:
f x y | simplecase x y = simpleanswer
f p1 p2 = ...
f p3 p4 = ...
...
There's no neat way to write this with if-then-else: you need to split f into
two functions
f x y = if simplecase x y then simpleanswer else f' x y
f' p1 p2 = ...
...
That's the reason Haskell has two binding constructions.
John Hughes