# Lecture 16 — 2015-11-02

## Recursive types; midterm debriefing

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

**Sum types**

We first covered sum types, which are the “math” version of Haskell’s `Either`

datatype.

```
t ::= ... | t1 + t2
e ::= ... | left e | right e | case e of left x -> e1 | right y -> e2
G |- e : t1
---------------------
G |- left e : t1 + t2
G |- e : t2
---------------------
G |- right e : t1 + t2
G |- e : t1 + t2
G,x:t1 |- e1 : t1
G,y:t2 |- e2 : t2
-------------------------
G |- case e of : t
left x -> e1
right y -> e2
```

The above rules are “extrinsic” typing rules, since `left`

and `right`

end up guessing their arguments. We could write subscripted versions (using `_`

), like below, to come up with intrinsic forms:

```
t ::= ... | t1 + t2
e ::= ... | left_t2 e | right_t1 e | ...
G |- e : t1
---------------------
G |- left_t2 e : t1 + t2
G |- e : t2
---------------------
G |- right_t1 e : t1 + t2
```

Note how the left and right constructors are annotated with the type of the *other* side: `left_t2`

says what type the programmer thinks the right side should have.

What values have type `t1 + t2`

? Constructors make values; we’ll say that a constructor applied to a value is a value.

```
v ::= ... | left v | right v
---------------------------- CaseLeft
case left v of --> e1[v/x]
left x -> e1
right y -> e2
---------------------------- CaseLeft
case right v of --> e2[v/y]
left x -> e1
right y -> e2
```

We can also give big-step rules, using environments:

```
e, env VV left v e1,env[v/x] VV v'
------------------------------------- CaseLeft
case e of , env VV v'
left x -> e1
right y -> e2
e, env VV left v e2,env[v/y] VV v'
------------------------------------- CaseRight
case e of , env VV v'
left x -> e1
right y -> e2
```

**Recursive types**

Recursion in Haskell functions and Haskell datatypes uses *names*. Recursion in the pure lambda calculus uses the Y combinator to write “closed-form” recursive functions. We use μ types to write closed-form recursive datatypes.

Note that `fold_{mu alpha. t}`

is meant to be interpreted as a subscript.

```
t ::= ... | mu alpha. t | alpha
e ::= ... | fold_{mu alpha. t} e | unfold e
G |- e : t[mu alpha. t/a]
---------------------------------------
G |- fold_{mu alpha. t} e : mu alpha. t
G |- e : mu alpha. t
--------------------------------
G |- unfold e : t[mu alpha. t/a]
```

These definitions are hard to understand at first blush. Let’s look at the definition for integer lists in Haskell and work our way down:

```
data IntList =
Nil
| Cons Int IntList
```

An `IntList`

is either:

`Nil`

, or`Cons n l`

, such that`n`

is an`Int`

and`l`

is an`IntList`

.

In algebraic types, we interpret ‘either’ using sums (written + in math and `Either`

in Haskell). So in pseudo-Haskell, we have:

`IntList = Nil + Cons Int IntList`

Next, we don’t use constructor names in algebraic datatypes—we just represent the data. So `Nil`

and `Cons`

need to be replaced. Now, `Nil`

has no arguments—the only information `Nil`

provides is that it isn’t `Cons`

. We can represent it using `()`

, the unit type.

`IntList = () + Cons Int IntList`

`Cons`

, on the other hand, has some arguments. We’ll represent them as a pair, using * (or × on paper, or `(,)`

in Haskell).

`IntList = () + (Int,IntList)`

At this point, the only left to do is to get rid of the recursion. To do this, we use μ. The process is mechanical: if you have a definition of the form `X = [some type t in terms of X]`

, you translate it to `X`

= μ α. t[^{α}/_{X}]. Here, that gives us:

`X = mu alpha. () + (Int,alpha)`

Okay: what values have μ types?

```
v ::= ... | fold_{mu alpha. t} v
-----------------------------------
unfold (fold_{mu alpha. t} v) --> v
```

We can also give rules in a big-step style:

```
e, env VV fold_{mu alpha. t} v
------------------------------
unfold e, env VV v
```

Hmm… still not helping. How do we build a value with folds? Let’s use the IntList above to build some lists.

```
IntList = mu alpha. () + (Int,alpha)
nil :: IntList
nil = fold_IntList (left ())
```

Okay… what about a list with elements? I’ll just write `fold`

without its subscript, to keep things brief.

`[1,2,3] = fold (right (1,fold (right (2,fold (right (3,fold (left ())))))))`

Okay… how do we define `cons`

?

```
cons :: Int -> IntList -> IntList
cons = \x. \xs. fold (right (x,xs))
```

What about `head`

and `tail`

?

```
head :: IntList -> Int
head xs =
case unfold xs of
left x -> diverge
right y -> fst y
tail :: IntList -> IntList
tail xs =
case unfold xs of
left x -> diverge
right y -> snd y
```

What about `map`

?

```
map :: (Int -> Int) -> IntList -> IntList
map f xs =
case unfold xs of
left e -> nil
right c -> cons (f (head c)) (map f (tail c))
```

**Midterms**

Midterms were handed back at the end of class. If you don’t have yours, I’ll bring it by on Wednesday.

Please check my arithmetic and data entry on Sakai!