Prove:  map f x ++ map f y = map f (x ++ y).

-- List all the definitions and equations you use.
-- label each with a name

1 map f [] = []
2 map f (x:xs) = (f x) : (map f xs)

3 [] ++ ys = ys
4 (x:xs) ++ ys = x : (xs ++ ys)

-- Set up the structure of the proof
Prove 3 things

1) map f [] ++ map f y = map f ([] ++ y)

2) Assuming:    map f zs ++ map f y = map f (zs ++ y)
   Prove:       map f (z:zs) ++ map f y = map f ((z:zs) ++ y)

3) map f bottom ++ map f y = map f (bottom ++ y)

-- label each step with the label of the definition
-- or equation that justifes it.

1) map f [] ++ map f y = map f ([] ++ y)
Proceed by transforming LHS into RHS with meaning preserving steps

 map f [] ++ map f y   -->    (By 1)
[] ++ map f y          -->    (By 3)
map f y                -->    (By 3 backwards)
map f ([] ++ y)               QED

2) Assuming:    map f zs ++ map f y = map f (zs ++ y)  (IH)
   Prove:       map f (z:zs) ++ map f y = map f ((z:zs) ++ y)

   Proceed by transforming LHS into RHS with meaning preserving steps

map f (z:zs) ++ map f y          (By 2)
(f z) : (map f zs ++ map f y)    (By IH)
(f z) : map f (zs ++ y)          (By 2 backwards)
map f (z: (zs ++ y))             (By 4 backwards)
map f ((z:zs) ++ y)              QED

3) map f bottom ++ map f y = map f (bottom ++ y)
Proceed by transforming both sides using laws about
pattern matching on bottom

map f bottom ++ map f y = map f (bottom ++ y)
bottom ++ map f y       = map f bottom
bottom                  = bottom

--------------------------------------------------------

In general you want to prove some thing about a formula: F
Pick a variable: x (the choice is important) such that
E(x) = F

Now you need to prove 3 things

1) E([])

2) Assuming:    E(zs)
   Prove:       E(z:zs)

3) E(bottom)

----------------------------------
In our last example

E(x) = map f x ++ map f y = map f (x ++ y).

We could have chosen y as the variable

E(y) = map f x ++ map f y = map f (x ++ y)

But this is much harder to prove. Lets try it

1) Prove E([])  =  map f x ++ map f [] = map f (x ++ [])
Proceed by transforming LHS into RHS with meaning preserving steps

map f x ++ map f []   --> (By 1)
map f x ++ []         --> Now what do we do? No definitions apply

So the choice of variable matters

----------------------------------------------------------
Lets choose one law from from the Laws worksheet

9) xs ++ []           = xs

Now the choice of variable is easy (there is only 1 variable)

E(x) =  xs++[] = xs

1) E([])                     []++[] = []


2) Assuming:    E(zs)        zs++[] = zs
   Prove:       E(z:zs)      (z:zs)++[] = (z:zs)


3) E(bottom)                 bottom++[] = bottom


------------------------
1) []++[] = []  (Trivial by 3)

2) Assuming:  zs++[] = zs
   Prove:    (z:zs)++[] = (z:zs)

   (z:zs)++[]   -->  (By 4)
   z:(zs++[])   -->  (By IH)
   z:(zs)       -->  (By parenthesis rule)
   z:zs         -->  QED

3) bottom++[] = bottom   (Trivial by pattern matching over bottom rule)

------------------------------------------------
Final Example

length . map f     = length
We'll need a rule for defining composition and length

5  (f . g) x = f(g x)

6 length [] = 0
7 length(x:xs) = 1 + length xs

-----------------------------
-- Set up proof

Reformulate law using law of extensionality.  Forall x f g. (f x)=(g x) iff f=g

(length . map f) x    = length x

E(x) = (length . map f) x    = length x

1) E([])                    (length . map f) []   = length []

2) Assuming:    E(zs)       (length . map f) zs    = length zs
   Prove:       E(z:zs)     (length . map f) (z:zs)    = length (z:zs)

3) E(bottom)                (length . map f) bottom    = length bottom

--------------------------------

1)  (length . map f) []   = length []

(length . map f) []   -->  By 6
[]                    -->  By 6 backwards
length []             QED

2) Assuming: (length . map f) zs    = length zs
   Prove:    (length . map f) (z:zs)    = length (z:zs)

(length . map f) (z:zs)   --> By 5
length(map f (z:zs))      --> By 2
length((f z):map f zs)    --> 7
1 + length(map f zs)      --> By 5
1 + ((length . map f) zs) --> By IH
1+ length zs              --> By 7 backwards
length (z:zs)             QED

3) (length . map f) bottom    = length bottom

(length . map f) bottom    -->  By 5
length(map f bottom)       -->  By pattern match on bottom
length bottom              QED

-----------------------------------------------
-- So what about proofs about trees?

data Tree a = Tip | Node a | Fork (Tree a) (Tree a)

 8 mapTree f Tip = Tip
 9 mapTree f (Node x) = Node(f x)
10 mapTree f (Fork l r) = Fork (mapTree f l) (mapTree f r)

11 depth Tip = 0
12 depth (Node x) = 1
13 depth (Fork l r) = 1 + (max (depth l) (depth r))

--------------------------------------------------
prove: depth(mapTree f x) = depth x

For trees the structure of a proof (E(x) = predicate) is

1) Prove E(Tip)
2) Prove E(Node x)
3) Assuming E(x) and E(y)  Prove E(Node x y)
4) Prove E(bottom)

-------------------------------------------

1) Prove E(Tip)                depth(mapTree f Tip) = depth Tip
depth(mapTree f Tip)  --> By 8
depth Tip             QED


2) Prove E(Node x)             depth(mapTree f (Node x)) = depth (Node x)
depth(mapTree f (Node x))  -->   By 9
depth(Node (f x))          -->  12
1                          -->  12 backwards
depth (Node x)             QED


3) Assuming:  E(x) and         IH1 depth(mapTree f x) = depth x
              E(y)             IH2 depth(mapTree f y) = depth y
   Prove:     E(Fork x y)      depth(mapTree f (Fork x y)) = depth (Fork x y)

depth(mapTree f (Fork x y))                               --> By 10
depth(Fork (mapTree f x) (mapTree f y))                   --> Byb 13
1 + (max (depth(mapTree f x)) (depth(mapTree f y))))      --> By IH1 and IH2
1 + max (depth x) (depth y)                               --> By 13 backwards
depth(Fork x y)                                           QED


4) Prove E(bottom)             depth(mapTree f bottom) = depth bottom
depth(mapTree f bottom)
depth bottom

------------------------------------------------------------
-- Patterns

1) A Datatype with n constructors has (n+1) cases
2) One for each case and one for bottom
3) For every inductive Construuctor you get an IH