# Let vs. Where

### From HaskellWiki

(let is an expression) |
|||

Line 7: | Line 7: | ||

In contrast to that, <hask>where</hask> is bound to a surrounding syntactic construct, |
In contrast to that, <hask>where</hask> is bound to a surrounding syntactic construct, |
||

like the [[pattern matching]] line of a function definition. |
like the [[pattern matching]] line of a function definition. |
||

+ | |||

+ | == Advantages of let == |
||

Consider you have the function |
Consider you have the function |
||

Line 39: | Line 41: | ||

</haskell> |
</haskell> |
||

+ | == Advantages of where == |
||

+ | Because "where" blocks are bound to a syntactic construct, they can be used to share bindings between parts of a function that are not syntactically expressions. For example: |
||

+ | |||

+ | <haskell> |
||

+ | f x |
||

+ | | cond1 x = a |
||

+ | | cond2 x = g a |
||

+ | | otherwise = f (h x a) |
||

+ | where |
||

+ | a = w x |
||

+ | </haskell> |
||

+ | |||

+ | In expression style, the guard structure would be lost, and the heavier lexemes arguably make the resulting function harder to read: |
||

+ | |||

+ | <haskell> |
||

+ | f x |
||

+ | = let a = w x |
||

+ | in if cond1 x |
||

+ | then a |
||

+ | else if cond2 x |
||

+ | then g a |
||

+ | else f (h x a) |
||

+ | </haskell> |
||

+ | |||

+ | == Lambda Lifting == |
||

+ | |||

+ | One other approach to consider is that let or where can often be implemented using [[lambda lifting]] and [[let floating]], incurring at least the cost of introducing a new name. The above example: |
||

+ | |||

+ | <haskell> |
||

+ | f x |
||

+ | | cond1 x = a |
||

+ | | cond2 x = g a |
||

+ | | otherwise = f (h x a) |
||

+ | where |
||

+ | a = w x |
||

+ | </haskell> |
||

+ | |||

+ | could be implemented as: |
||

+ | |||

+ | <haskell> |
||

+ | f x = f' (w x) x |
||

+ | |||

+ | f' a x |
||

+ | | cond1 x = a |
||

+ | | cond2 x = g a |
||

+ | | otherwise = f (h x a) |
||

+ | </haskell> |
||

+ | The auxilliary definition can either be a top-level binding, or included in f using let or where. |
||

[[Category:Style]] |
[[Category:Style]] |

## Revision as of 03:00, 14 November 2007

Haskell programmers often wonder, whether to useThis seems to be only a matter of taste in the sense of "Declaration vs. expression_style", however there is more about it.

It is important to know thatthat is, it can be written whereever expressions are allowed.

In contrast to that,like the pattern matching line of a function definition.

## 1 Advantages of let

Consider you have the function

f :: s -> (a,s) f x = y where y = ... x ...

However, transforming to

f :: State s a f = State $ \x -> y where y = ... x ...

f :: s -> (a,s) f x = let y = ... x ... in y

This is easily transformed to:

f :: State s a f = State $ \x -> let y = ... x ... in y

## 2 Advantages of where

Because "where" blocks are bound to a syntactic construct, they can be used to share bindings between parts of a function that are not syntactically expressions. For example:

f x | cond1 x = a | cond2 x = g a | otherwise = f (h x a) where a = w x

In expression style, the guard structure would be lost, and the heavier lexemes arguably make the resulting function harder to read:

f x = let a = w x in if cond1 x then a else if cond2 x then g a else f (h x a)

## 3 Lambda Lifting

One other approach to consider is that let or where can often be implemented using lambda lifting and let floating, incurring at least the cost of introducing a new name. The above example:

f x | cond1 x = a | cond2 x = g a | otherwise = f (h x a) where a = w x

could be implemented as:

f x = f' (w x) x f' a x | cond1 x = a | cond2 x = g a | otherwise = f (h x a)

The auxilliary definition can either be a top-level binding, or included in f using let or where.