# Let vs. Where

### From HaskellWiki

(use 'select') |
|||

Line 54: | Line 54: | ||

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

− | In expression style, you might | + | In expression style, you might use an explicit <hask>case</hask>: |

− | in | + | |

+ | <haskell> | ||

+ | f x | ||

+ | = let a = w x | ||

+ | in case () of | ||

+ | _ | cond1 x = a | ||

+ | | cond2 x = g a | ||

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

+ | </haskell> | ||

+ | |||

+ | or a [[Case|functional equivalent]]: | ||

+ | |||

<haskell> | <haskell> | ||

f x = | f x = | ||

Line 64: | Line 75: | ||

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

− | + | or a series of if-then-else expressions: | |

− | + | ||

<haskell> | <haskell> | ||

Line 76: | Line 86: | ||

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

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

+ | |||

+ | These alternatives are arguably less readable and hide the structure of the function more than simply using <hask>where</hask>. | ||

== Lambda Lifting == | == Lambda Lifting == | ||

Line 101: | Line 113: | ||

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

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

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

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

## Revision as of 01:37, 15 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

f x = let a = w x in case () of _ | cond1 x = a | cond2 x = g a | otherwise = f (h x a)

or a functional equivalent:

f x = let a = w x in select (f (h x a)) [(cond1 x, a), (cond2 x, g a)]

or a series of if-then-else expressions:

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)