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.
