# Induction and Recursion
Today we will practice proving behavioral equivalence of expressions
involving variants and functions.
##### Exercise: behead [✭]
Prove that for any list `xs` and element `x`,
`behead (prepend xs x) ~ xs`, where `prepend` and `behead`
are defined as follows:
```
let prepend xs x =
x::xs
let behead = function
| [] -> []
| _::t -> t
```
*Hint: induction is not needed.*
□
##### Exercise: noop [✭✭]
Prove that for any list `xs`, `noop xs ~ xs`,
where `noop` is defined as follows:
```
let rec noop = function
| [] -> []
| h::t -> h :: noop t
```
Use the following template for an inductive proof:
```
Theorem: TODO(xs)
Proof: by induction on xs
Case: xs = []
Show: TODO
TODO
Case: xs=h::t
Show: TODO
IH : TODO
TODO
QED
```
##### Exercise: append assoc [✭✭]
Prove that for all lists `l1`, `l2`, and `l3`,
it holds that `l1 @ (l2 @ l3) ~ (l1 @ l2) @ l3`.
□
##### Exercise: size reflect [✭✭]
Prove that for all trees `t`, `size (reflect t) ~ size t`,
given the following definitions:
```
type 'a tree = Leaf | Branch of 'a * 'a tree * 'a tree
let rec reflect = function
| Leaf -> Leaf
| Branch(x,l,r) -> Branch(x, reflect r, reflect l)
let rec size = function
| Leaf -> 0
| Branch(x,l,r) -> 1 + size l + size r
```
□
##### Exercise: apply assoc [✭]
Prove that for all functions `f`, `g`, and `h` (of
appropriate types), `(f @@ g) @@ h ~ f @@ (g @@ h)`, where `(@@)`
is defined as follows:
```
let (@@) f g x = f (g x)
```
*Hint: use extensionality; induction is not needed.*
□
## Additional exercises
##### Exercise: map append [✭✭✭]
Prove that for all `f`, `xs`, and `ys`,
`map f (xs @ ys) = (map f xs) @ (map f ys)`, where
`map` and `(@)` are defined as follows:
```
let rec append l1 l2 =
match l1 with
| [] -> l2
| h::t -> h :: (append t l2)
let (@) = append
let rec map f = function
| [] -> []
| h::t -> (f h) :: map f t
```
□
##### Exercise: rev_append [✭✭✭]
Prove that for all lists `xs`, and for all
lists `ys`, `rev_append xs ys ~ (nrev xs) @ ys`, where `rev_append`
and `nrev` are defined as follows:
```
let rec rev_append l1 l2 =
match l1 with
| [] -> l2
| h::t -> rev_append t (h :: l2)
let rec nrev = function
| [] -> []
| h::t -> (nrev t) @ [h]
```
*Hint: use a previous exercise as a lemma.*
□
##### Exercise: rev [✭✭]
Next, prove that for all lists `xs`, `rev xs ~ nrev xs`, where
`rev` is defined as follows:
```
let rev xs = rev_append xs []
```
*Hint: Make use of previous exercises. You might discover that it would be
helpful to state and prove a relatively simple lemma involving `[]` and `@`.*
Note that this definition of `rev` is, in fact, how OCaml's `List.rev` is defined.
You have therefore proved the correctness of a tail-recursive implementation of list
reversal by showing its equivalence to a non-tail-recursive implementation.
□