# Unit 4: List comprehensions

## Introduction

List comprehensions are a convenient way of defining lists in Haskell. List comprehensions used to be called ZF-expressions. The following is an example of such an expression:

``````[ x * x | x <- [1, 2, 7, 12], even x ]
``````

This list comprehension is the list of all those things of the form `x * x` such that `x` is drawn from the list `[1, 2, 7, 12]` and `x` is even. Thus, the above evaluates to `[4, 144]`. The general form of a list comprehension is:

``````[ EXP | QUAL, ..., QUAL ]
``````

where `QUAL` is either a Boolean-valued expression or a generator. A generator has one of two forms: either `VARIABLE <- LIST` or `PATTERN <- LIST`.

## Alternative notation

The list comprehension displayed above can also be written using the `do`-notation. To use this you need to load the `Control.Monad` module:

``````ghci> import Control.Monad
ghci> do { x <- [1,2,7,12] ; guard (even x) ; return (x * x) }
[4,144]
``````

This works because lists constitute a monad. The `do`-notation is usually written without using curly brackets and semicolons like this:

``````do x <- [1,2,7,12]
guard (even x)
return (x * x)
``````

## Reduction rules for list comprehensions

The behaviour of list comprehension is completely determined by the following five reduction rules:

 (ZF1) `[ e | v <- [], q ]` reduces to `[]`, where `q` is a sequence of zero or more qualifiers. (ZF2) `[ e | v <- f:fs, q ]` reduces to `[ e | q ] [ v := f ] ++ [ e | v <- fs, q ]`, where `h [ v := f ]` represents `h` with all occurrences of `v` in it replaced by `f`. (ZF3) `[ e | False, q ]` reduces to `[]`. (ZF4) `[ e | True, q ]` reduces to `[ e | q ]`. (ZF5) `[ e | ]` reduces to `[ e ]`.

## Quicksort

Hoare's Quicksort algorithm can be expressed very concisely by using a couple of list comprehensions:

``````quick :: Ord a => [a] -> [a]
quick []     = []
quick [x]    = [x]
quick (x:xs) = quick [ u | u <- xs, u < x ]
++ [x] ++
quick [ u | u <- xs, u >= x ]
``````

© Antoni Diller (17 September 2021)