# Lecture 2 — 2015-09-07

## More Haskell

This lecture is written in literate Haskell; you can download the raw source.

`module Lec02 where`

We added this statement so that we could use definitions from Lec01.

`import Lec01 `

We started by writing some functions over the `IntTree`

structure that appears in the homework.

```
data IntTree =
Empty
| Node IntTree Int IntTree
deriving Show
leaf :: Int -> IntTree
leaf v = Node Empty v Empty
inorder :: IntTree -> [Int]
inorder Empty = []
inorder (Node l v r) = inorder l ++ [v] ++ inorder r
preorder :: IntTree -> [Int]
preorder Empty = []
preorder (Node l v r) = [v] ++ preorder l ++ preorder r
height :: IntTree -> Int
height Empty = 0
height (Node l _ r) = 1 + max (height l) (height r)
```

It took a minute to remember our BST invariants, but we wrote a simple lookup function.

```
memberBST :: Int -> IntTree -> Bool
memberBST _ Empty = False
memberBST v (Node l v' r)
| v == v' = True
| v < v' = memberBST v l
| v > v' = memberBST v r
```

Next, we tried to think about what it means for a tree to be balanced. We derived some requirements on the board and translated pretty directly to Haskell—nice!

```
balanced :: IntTree -> Bool
balanced Empty = True
balanced (Node l _ r) =
balanced l && balanced r &&
abs (height l - height r) <= 1
```

Once we tested on some bigger trees, we decided this was a bit too slow.

```
bigBalancedTree :: Int -> IntTree
bigBalancedTree 0 = Empty
bigBalancedTree n =
Node (bigBalancedTree (n-1)) 0 (bigBalancedTree (n-1))
bigUnbalancedTree :: Int -> IntTree
bigUnbalancedTree n
| n <= 0 = Node Empty 0 $ Node Empty 1 $ Node Empty 2 Empty
| even n = Node (bigUnbalancedTree (n-2)) 0 (bigUnbalancedTree (n-1))
| otherwise = Node (bigUnbalancedTree (n-1)) 0 (bigUnbalancedTree (n-2))
```

We rewrote our function to carefully computer balanced-ness and height at the same time, using pairs.

```
balanced' :: IntTree -> (Bool,Int)
balanced' Empty = (True,0)
balanced' (Node l _ r) =
let (bl,hl) = balanced' l in
let (br,hr) = balanced' r in
(bl && br && abs (hl - hr) <= 1, 1 + max hl hr)
```

After running `:set +s`

to get some performance stats, we played with some other performance-oriented code.

We saw two ways of writing auxiliary functions. At the top level:

```
fib' :: Int -> Int
fib' n = fibAux n 1 1
fibAux :: Int -> Int -> Int -> Int
fibAux 0 f1 f2 = f1
fibAux 1 f1 f2 = f2
fibAux n f1 f2 = fibAux (n-1) f2 (f1+f2)
```

And in a `where`

clause:

```
fib'' :: Int -> Int
fib'' n = fibAux n 1 1
where fibAux :: Int -> Int -> Int -> Int
fibAux 0 f1 f2 = f1
fibAux 1 f1 f2 = f2
fibAux n f1 f2 = fibAux (n-1) f2 (f1+f2)
```

I confusingly used the name `loop`

at first. There’s no `loop`

keyword in Haskell! It was just a name! A rose by another name would smell just as sweet.

We also looked at some lazy evaluation. First we had to check out some polymorphic functions, like `id`

(of type `a -> a`

) and `map`

(of type `(a->b)->[a]->[b]`

), and then `zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]`

, which led us to this incredible looking definition of the Fibonacci series:

```
fibs :: [Int]
fibs = 1:1:(zipWith (+) fibs (tail fibs))
```

The secret sauce in the above definition is *lazy evaluation*, which we’ll look at more later in the semester. If it didn’t make sense, don’t worry! We’ll see a bit more on Wednesday, and then more formally next week.

Finally, there was some talk about so-called “algebraic” datatypes, where we could define non-recursive datatypes using either the `data`

-style definitions or using `Either`

and tuples/pairs `(,)`

.

```
type Line' = Either Float (Float,Float)
mkLine :: Point -> Point -> Maybe Line
mkLine p1 p2 =
if xCoord p1 == xCoord p2
then if yCoord p1 == yCoord p2
then Nothing
else Just $ Vert $ xCoord p1
else
let m = (yCoord p1 - yCoord p2) /
(xCoord p1 - xCoord p2) in
let b = yCoord p1 - (m * xCoord p1) in
Just $ Sloped m b
either' :: (a -> c) -> (b -> c) -> Either a b -> c
either' l r (Left a) = l a
either' l r (Right b) = r b
```

As a final puzzle, we thought about how you might write down the algebraic datatype for `IntTree`

—it was recursive! We’ll look at these kinds of recursive definitions in more detail later in the course.