co89757

9/22/2014 - 1:35 AM

Gist for Haskell

#Start-out
Booleans: `&&, ||, not , ==, /=(not equal)`

Basic functions(prefix or use `` for infix):

`succ 8`

returns 9

Function syntax

*functions can't begin with uppercase letters.*

`[fname] [...args] = [expression]`

Control

`if [exp] then [exp] else [exp]`

*else* is mandatory

use `let [ex]`

for in-line name-defining.

`[ls]++[ls]`

for list appending. prepending `A:[list]`

is much cheaper than appending.

`[ls] !! index`

Use `!!`

for list access

**List functions**

`head [lst]`

to extract the 1st element

`tail [lst]`

to extract the rest of the list except 1st elem.

`last [lst]`

to put the last elem

`init [lst]`

to take all but last elem. `length [ls]`

, `null [ls]`

check for emptiness. `reverse [ls]`

`take # [ls]`

take the first # elements `drop # [ls]`

drops the first # elements and returns the list. `maximum/minimum [ls]`

`sum/product []`

`elem E [ls]`

checks for E's membership in the list

**ranges**

`[2..20]`

or `[2,4,..10]`

for range with a step

`[2,4..]`

infinite list

**list comprehension**

`[ [expression] | x <- [range] , [condition] ]`

**Tuples**

similar to tuples in C++. can be heterogeneous. `fst (a,b)`

and `snd (a,b)`

are 2 tuple element access functions

a useful function `zip`

(like Py) `zip [ls1] [ls2]`

creates a list with pairs

Haskell is *static-typing* language. `:t FOO`

use `:t`

to tell the type of an expression. `::`

means 'has the type of '

Functions also have types. When writing our own functions, we can choose to give them an explicit type declaration.

```
addThree :: Int -> Int -> Int -> Int
addThree x y z = x + y + z
```

**type variable**. That means that a can be of any type. This is much like generics in other languages,

```
ghci> :t head
head :: [a] -> a
```

A **typeclass** is a sort of interface that defines some behavior of a type

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

We see a new thing here, the `=>`

symbol. Everything before the => symbol is called a **class constraint**. We can read the previous type declaration like this: the equality function takes any two values that are of the same type and returns a Bool. The type of those two values must be a member of the Eq class (this was the class constraint).

Basic Typeclasses

`Eq`

for equity-checkable

`Ord`

for ordering

`Show`

has a string representation. a useful function: `show [exp]`

like `repr`

in Python. shows the string repr of an expression.

`Read`

and `read`

is the opposite. It interprets given representation and decodes it

```
ghci> read "True" || False
True
ghci> read "8.2" + 3.8
12.0
ghci> read "5" - 2
3
ghci> read "[1,2,3,4]" ++ [3]
[1,2,3,4,3]
```

**type annotation**

```
ghci> :t read
read :: (Read a) => String -> a
```

See? It returns a type that's part of Read but if we don't try to use it in some way later, it has no way of knowing which type. That's why we can use explicit type annotations. Type annotations are a way of explicitly saying what the type of an expression should be. We do that by adding :: at the end of the expression and then specifying a type. Observe:

```
ghci> read "5" :: Int
5
ghci> read "5" :: Float
5.0
ghci> (read "5" :: Float) * 4
20.0
```

```
sayMe :: (Integral a) => a -> String
sayMe 1 = "One!"
sayMe 2 = "Two!"
sayMe 3 = "Three!"
sayMe 4 = "Four!"
sayMe 5 = "Five!"
sayMe x = "Not between 1 and 5"
```

you can also pattern match in list comprehensions.

```
ghci> let xs = [(1,3), (4,3), (2,4), (5,3), (5,6), (3,1)]
ghci> [a+b | (a,b) <- xs]
[4,7,6,8,11,4]
```

Lists themselves can also be used in pattern matching. You can match with the empty list [] or any pattern that involves : and the empty list

*The x:xs pattern is used a lot*, especially with recursive functions. But patterns that have : in them only match against lists of length 1 or more.

```
head' :: [a] -> a
head' [] = error "Can't call head on an empty list, dummy!"
head' (x:_) = x
```

**Notice that if you want to bind to several variables (even if one of them is just _ and doesn't actually bind at all), we have to surround them in parentheses.**

```
tell :: (Show a) => [a] -> String
tell [] = "The list is empty"
tell (x:[]) = "The list has one element: " ++ show x
tell (x:y:[]) = "The list has two elements: " ++ show x ++ " and " ++ show y
tell (x:y:_) = "This list is long. The first two elements are: " ++ show x ++ " and " ++ show y
```

*you can't use ++ in pattern matches.*

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

```
bmiTell :: (RealFloat a) => a -> a -> String
bmiTell weight height
| bmi <= 18.5 = "You're underweight, you emo, you!"
| bmi <= 25.0 = "You're supposedly normal. Pffft, I bet you're ugly!"
| bmi <= 30.0 = "You're fat! Lose some weight, fatty!"
| otherwise = "You're a whale, congratulations!"
where bmi = weight / height ^ 2
```

We use `where`

clause for local variables and functions

The names we define in the where section of a function are only visible to that function, so we don't have to worry about them polluting the namespace of other functions. Notice that **all the names are aligned at a single column**. If we don't align them nice and proper, Haskell gets confused because then it doesn't know they're all part of the same block.** where bindings aren't shared across function bodies of different patterns** see below

```
initials :: String -> String -> String
initials firstname lastname = [f] ++ ". " ++ [l] ++ "."
where (f:_) = firstname
(l:_) = lastname
```

The form is `let <bindings> in <expression>`

. The names that you define in the let part are accessible to the expression after the in part. Let bindings let you bind to variables anywhere and are expressions themselves, but are very local, so they don't span across guards. Just like any construct in Haskell that is used to bind values to names, let bindings can be used for pattern matching.

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

**The difference is that let bindings are expressions themselves. where bindings are just syntactic constructs.**

They can also be used to introduce functions in a local scope:

If we want to bind to several variables inline, we obviously can't align them at columns. That's why we can separate them with semicolons.

```
ghci> 4 * (let a = 9 in a + 1) + 2
42
ghci> [let square x = x * x in (square 5, square 3, square 2)]
[(25,9,4)]
ghci> (let a = 100; b = 200; c = 300 in a*b*c, let foo="Hey "; bar = "there!" in foo ++ bar)
(6000000,"Hey there!")
```

```
case expression of pattern -> result
pattern -> result
pattern -> result
...
```

EXAMPLE:

```
head' :: [a] -> a
head' xs = case xs of [] -> error "No head for empty lists!"
(x:_) -> x
```

Whereas pattern matching on function parameters can only be done when defining functions, case expressions can be used pretty much anywhere

```
describeList :: [a] -> String
describeList xs = "The list is " ++ case xs of [] -> "empty."
[x] -> "a singleton list."
xs -> "a longer list."
```

They are useful for pattern matching against something in the middle of an expression. Because pattern matching in function definitions is syntactic sugar for case expressions, we could have also defined this like so:

```
describeList :: [a] -> String
describeList xs = "The list is " ++ what xs
where what [] = "empty."
what [x] = "a singleton list."
what xs = "a longer list."
```