## Lists

Lists are constructed one element at a time starting from an empty **[]** list using the *cons* operator **:**. For example, **[1,2,3]** can be decomposed as:

```haskell
[1,2,3]
--
1 : [2,3]
--
1 : (2 : [3])
--
1 : (2 : (3 : []))
```

To verify if a list with 3 numbers starts with the integer **1**, you can use pattern matching.

```haskell
startsWithOne :: [Int] -> Bool
startsWithOne [1, _, _] = True
startsWithOne _         = False
```

### Access elements

To access an element in a list, the indexing operator **!!** can be used.

```haskell
-- Get the third element of a list.
third :: [a] -> a
third xs = xs !! 2
```

### list comprehension

* Wikipedia: [List comprehension](https://en.wikipedia.org/wiki/List_comprehension).


```haskell
ghci> [x^2 | x <- [1..6]]
-- [1,4,9,16,25,36]
```

* The **|** symbol is read as: "*such that*".
* The **<-** symbol is read as: "*drawn from*".
* And **x <- [1..6]** is called a: "*generator*".

A list comprehension can have more than one generator.

```haskell
ghci> [(x,y) | x <- [1,2,3], y <- [4,5]]
-- [(1,4),(1,5),(2,4),(2,5),(3,4),(3,5)]
```

Examples of list comprehensions:

```haskell
halve :: [Int] -> ([Int], [Int])
halve xs =
    ([x | x <- xs, x < 4], [x | x <- xs, x >= 4])

-- halve [1,2,3,4,5,6]
-- ([1,2,3],[4,5,6])
```

How to actually halve the list properly:

```haskell
halve :: [Int] -> ([Int], [Int])
halve xs =
    (take n xs, drop n xs)
    where n = length xs `div` 2
-- or
    splitAt (length xs `div` 2) xs
```

Here the **length** function replaces all elements with a 1 and sums the total:

```haskell
length :: [a] -> Int
length xs = sum [1 | _ <- xs]
length [1,4,8,90]
-- 4
```

You can use logical expressions as a **guard**, to filter values created by list comprehensions.

```haskell
factors :: Int -> [Int]
factors n = [x | x <- [1..n], n `mod` x == 0]

factors 20
-- [1,2,4,5,10,20]
factors 13
-- [1,13]
```

And you can use this **factors** function to determine **prime** numbers.

* Wikipedia: [Prime number](https://en.wikipedia.org/wiki/Prime_number)

```haskell
prime :: Int -> Bool
prime n = factors n == [1,n]

prime 15
--False
prime 13
-- True
```
And with this **prime** function, we can use list comprehension to determine a range of prime numbers!

```haskell
primes :: Int -> [Int]
primes n = [x | x <- [2..n], prime x]

primes 50
-- [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47]
```

