# List comprehensions in Haskell

List comprehensions are a powerful idiom to generate new lists from old ones.

## Syntax

```
[e | gnr1,.., grd1,..]
```

So we wrap inside square brackets an expression that will generate new list followed by `|`

and then one or more *generators* and optionally one or more *guards*. Generators generate the elements of the older list. For example, `x <- [1..10]`

generates a list of integers 1 through 10 and assign these to `x`

one by one. `x`

then can be used in `e`

. Guards help to filter out elements that we don't want in the new list. As a concrete example, the expression:

```
[x | x <- [1..10], even x]
```

will generate the list

```
[2, 4, 6, 8, 10]
```

and can be read as *get me a list of all even numbers drawn from list [1..10]*

## More examples

### Length of a list

```
length :: [a] -> Int
length xs = sum [1 | _ <- xs]
```

So we can do pattern matching on generators.

### Return number of upper case letters in a string

```
uppers :: String -> Int
uppers xs = length [x | x <- xs, Data.Char.isUpper x]
```

### Pairwise sum of two lists of numbers

```
pairSum :: Num a => [a] -> [a] -> [a]
pairSum xs ys = [x+y | (x,y) <- zip xs ys]
```

Here the library function `zip`

is used to create list of pairs that are pattern-matched in the generator. Components of pairs are then added to create the final list.

### Scalar product of two lists of integers

Scalar product is defined as: $$\sum_{i=0}^{n-1} (xs_i * ys_i)$$

```
scalarproduct :: [Int] -> [Int] -> Int
scalarproduct xs ys = sum [a*b | (a,b) <- zip xs ys]
```

Notice how the formula nicely translates to code.

### Concat

`concat`

is a library function that *flattens* a list of list. We can write that using list comprehension as

```
concat :: [[a]] -> [a]
concat xss = [x | xs <- xss, x <- xs]
```

Here we are using two generators. For multiple generators, we have to think each subsequent generator nested a level deeper than the previous one, like nested *for loops* in imperative programming. So here, `xs`

is drawn from the input list, and thus each `xs`

is a list. For each `xs`

, second generator (`x <- xs`

) draws an element to build a new list.

### Pythagorean triples

A triple $(x,y,z)$ of positive integers is *Pythagorean* if it satisfies the equation $x^2+y^2 = z^2$.

```
pyths :: Int -> [(Int, Int, Int)]
pyths n = [(x,y,z) | x <- [1..n], y <- [1..n], z <- [1..n],
x^2 + y^2 == z^2]
```

```
*Main> pyths 10
[(3,4,5),(4,3,5),(6,8,10),(8,6,10)]
```