19 Oct

# Lists

**Empty** list: `[]`

**Prepending**:

```
> 1 : [2, 3]
[1, 2, 3]
> 'a' : "bcd"
"abcd"
```

**Appending**/concatenating:

```
> [1, 2] ++ [3, 4]
[1, 2, 3, 4]
> [1] ++ [2, 3]
[1, 2, 3]
> "ab" ++ "cd"
"abcd"
```

**Extracting**:

```
> head [1, 2, 3]
1
> tail [1, 2, 3]
[2, 3]
> last [1, 2, 3]
3
> drop 2 [1, 2, 3, 4, 5] -- last two elements
[4, 5]
> "abc" !! 1 -- arbitrary index
'b' -- zero-based index
```

**Signature** types:

```
squares :: [Int] -> [Int] -- takes a list of integers and returns a list of integers
```

**Ranges**:

```
> [1..5]
[1,2,3,4,5]
> [5..1] -- won't implicitly work for reverse
[]
> [1..]
[1, 2, 3, 4, 5, 6, 7, ...] -- will run to infinity
> ['a'..'e'] -- letters too
"abcde"
```

# Recursion

*Square every element*: `squares [1, 2, 3]`

is `[1, 4, 9]`

Manipulating elements in a list one by one, the following are equivalent:

```
-- descriptive, list comprehension
squares xs = [x^2 | x <- xs] -- x^2 is equivalent to x*x
-- equational recursion
squares [] = []
squares (x:xs) = x^2 : squares xs -- list with head x and tail xs
-- conditional recursion
squares l =
if l == [] then []
else x^2 : squares xs
where x = head l
xs = tail l
-- conditional recursion (with let..in)
squares l =
if l == [] then []
else let x = head l
xs = tail l
in x^2 : squares xs
```

*Square only even elements*: `squareEvens [1, 2, 3, 4]`

is `[4, 16]`

Manipulating elements *if* they match a condition, the following are equivalent:

```
-- descriptive
squareEvens xs = [x^2 | x <- xs, even x] -- 'even' is a built-in equivalent to (x `mod` 2 == 0)
-- pattern matching
squareEvens [] = []
squareEvens (x:xs)
| even x = x : squareEvens xs
| otherwise = squareEvens xs
```