# 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]] | ||

[[Category:Syntax]] | [[Category:Syntax]] |

## 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.