# Haskell

# Lists

*Append lists*

```
> [1,2,3] ++ [7,8,9]
[1,2,3,7,8,9]
> "Hello" ++ " " ++ "Haskell!"
"Hello Haskell!"
> ['h','e'] ++ ['y','a']
"heya"
```

*Prepend to list*

```
> 4:[1,2,3]
[4,1,2,3]
> 1:2:3:[]
[1,2,3]
```

**Note:** Prepending *much* more performant on large lists.

*Index a list*

```
> [1,2,3] ! 0
1
> [1,2,3] ! 2
3
> [1,2,3] ! 3
Exeption
```

*Core functions*

Function | Description |
---|---|

head | Return the first element in a list. |

tail | Return everything except the head. |

last | Return the last element in a list. |

init | Return everything except the last element. |

length | Return the length of a list. |

null | Check if a list is empty. |

reverse | Reverse a list. |

take | Take n elements from beginning of list. |

drop | Drop n elements from beginning of list. |

maximum | Return the biggest element in a list. |

minimum | Return the smallest element in a list. |

sum | Return the sum of a list of numbers. |

product | Return the product of a list of numbers. |

elem | Check if n exists in a list. |

*Ranges*

```
> [1..5]
[1,2,3,4,5]
> ['a'..'e']
['a','b','c','d','e']
> [2,4..10]
[2,4,6,8,10]
```

**List Comprehensions**

Ranges are easy and very useful. However, if you want to construct a list from a more complicated pattern than linear growth, you will need to use something else. Haskell provides List Comprehensions for this purpose.

```
> [ x*x | x <- [1..5] ]
[1,4,9,16,25]
```

You can also pass in multiple lists.

```
> [ [x,y] | x <- [1,2,3], y <- [7,8,9] ]
[[1,7],[1,8],[1,9],[2,7],[2,8],[2,9],[3,7],[3,8],[3,9]]
```

*Conditions*

You can add any number of conditions to a list comprehesions.

```
> [ x*x | x <- [1..10], x >= 50 ]
[64,81,100]
> [ x | x <- [50..100], x ‘mod‘ 7 == 3]
[52 ,59 ,66 ,73 ,80 ,87 ,94]
> [ x | x <- [1..5], x /= 2, x /= 4 ]
[1,3,5]
```

# Tuples

# Types

Haskell is a type-safe language. This makes it possible for GHC to catch many errors at compile time, making your (compilable) code much more reliable. However, unlike other type-safe languages such as Java, Haskell implements *type inference*. In other words, Haskell will infer what a given type should be without you having to state it explicitly.

Everything in Haskell has a type. To view the type, you can use the `:t`

command.

```
> :t ’a’
’a’ :: Char
> :t True
True :: Bool
> :t "HELLO!"
"HELLO!" :: [Char]
> :t (True, ’a’)
(True, ’a’) :: (Bool, Char)
> :t 4 == 5
4 == 5 :: Bool
```

Type | Description |
---|---|

Int | Bounded integer like in C |

Integer | Unbounded integer. Can be inefficient. |

Float | Single precision floating point integer. |

Double | Double precision floating point integer. |

Bool | True or false. |

Char | Single character. |

*Type Definition*

Although not necessary, it’s good practice to supply a type declaration before your function.

`<func> :: <:t param> -> <:t retval>`

```
removeNonUppercase :: [Char] => [Char]
removeNonUppercase xs = [ x | x <- xs, x 'elem' ['A'..'Z'] ]
```

If your function takes multiple parameters, separate those with `->`

as well. The last in the chain is always the return value.

`<func> :: <:t p1> -> <:t p2> -> ... -> <:t retval>`

```
> :t take
take :: Int -> [a] -> [a]
```

Some functions can accept parameters of any type. These are called *type variables* and are typically denoted by a,b,c,d,…

```
> :t fst
fst :: (a, b) -> a
```

# Typeclasses

Types can be grouped as *Typeclasses*. If a type is member of a certain typeclass, that means it supports certain behavior that the typeclass implements. You can impose *type contraints* in your type definitions using the `=>`

symbol.

```
> :t (==)
(==) :: Eq a => a -> a -> Bool
```

This means that the == function accepts two variables of the same arbitrary type and retuns a boolean. However, that type must be a member of the `Eq`

typeclass. The Eq typeclass allows Haskell to test for equality.

Typeclass | Description |
---|---|

Eq | Supports equality testing (== and /=). |

Ord | Supports ordering (>, <, >=, <=). |

Show | Supports conversion to a string. |

Read | Supports converting from a string. |

Enum | Supports sequential ordering. |

Bounded | Has an upper and lower bound. |

Num | Supports numberic functions (+, -, *, /). |

Integral | Includes only whole numbers (Int, Integer). |

Floating | Includes only floating point numbers (Float, Double). |

# Functions

**Pattern Mathing**

Haskell allows you to create multiple function definitions. This is useful for handling error cases and corner cases.

```
factorial :: (Integral a) => a -> a
factorial 0 = 1
factorial n = n * factorial (n - 1)
```

```
length' :: (Num b) => [a] -> b
length' [] = 0
length' (_:xs) = 1 + length' xs
```

```
sum' :: (Num a) => [a] -> a
sum' [] = 0
sum' (x:xs) = x + sum' xs
```

**As Patterns**

As patterns are a handy way to pattern match without destructuring the original input. You use an `@`

symbol for this.

```
firstLetter :: String -> String
firstLetter "" = "The string is empty"
firstLetter all@(x:xs) = "The first letter of " ++ all ++ " is " ++ [x]
```

**Guards**

Guards are similar to if statements. They allow you to apply conditional logic to patterns. You put a `|`

in front of each guard.

```
max' :: (Ord a) => a -> a -> a
max' a b
| a > b = a
| otherwise = b
```

```
compare :: (Ord a) => a -> a -> Ordering
a 'compare' b
| a > b = GT
| a == b = EQ
| b < a = LT
```

**Where Binding**

```
initials :: String -> String -> String
initials firstName lastName = [f] ++ [l]
where (f:_) = firstName
(l:_) = lastName
initials firstName middleName lastName = [f] ++ [m] ++ [l]
where (f:_) = firstName
(m:_) = middleName
(l:_) = lastName
```

```
calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [bmi w h | (w, h) <- xs]
where bmi weight height = weight / height ^ 2
```

**Let Binding**

Another useful construct is the `let`

binding. Unlike the `where`

binding which is just a syntactic construct, the `let`

bunding is an expression. This makes it much more versitile. You can use `let`

just about anywhere.

```
cylinderArea :: (RealFloat a) => a -> a -> a
cylinderArea r h =
let sideArea = 2 * pi * r * h
topArea = pi * r ^ 2
in sideArea + 2 * topArea
```

```
> 4 * (let a = 99 in a + 1) + 20
420
```

```
calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [ bmi | (w, h) <- xs, let bmi = w / h ^ 2 ]
```

Here’s an implementation of quicksort.

```
quicksort :: (Ord a) => [a] -> [a]
quicksort [] = []
quicksort (x:xs) =
let smallSorted = quicksort [ a | a <- xs, a <= x ]
bigSorted = quicksort [ a | a <- xs, a > x ]
in smallSorted ++ [x] ++ bigSorted
```