Lifting pattern

From HaskellWiki

For another meaning of the word lifting, see Lifting.

The lifting pattern is to float bindings to a higher level in the program.

Examples

reverse xs = rev' xs []
 where
  rev' [] ys = ys
  rev' (x:xs) ys = rev' xs (x:ys)

becomes:

reverse xs = rev' xs []

rev' [] ys = ys
rev' (x:xs) ys = rev' xs (x:ys)

You can always do this if the function is a Combinator. You can convert non-combinators into combinators using Lambda lifting.

This is also known as Let floating.

HaWiki original by User:AndrewBromage

Reasons to apply this pattern

A major reason is that sometimes bindings are sufficiently generic that they are useful in other contexts. You can avoid rewriting common things by lifting them. The prelude contains many things that could have started out as helper functions at one point but which have been lifted to the program and finally to the language level due to the fact that they are generically useful. Especially the many simple but useful list functions. Indeed, if one is not aware of what is in the prelude, one will probably end up writing at least a few of those on one's own. User:CaleGibbard


Another reason is testability. In the first version, you can't directly test the unlifted function (say, using one of the Unit testing frameworks). By lifting the definition to the outer level, you can directly test it.

The real motivation, though, is that Refactoring steps often go together. Lifting may not be so useful on its own, but applying some other Refactorings first may turn your definition into a form where it's then useful in other contexts. Lifting the definition then makes it available to other functions which may want to use it.User:AndrewBromage