Induction Over Haskell Data Structures (Full Notes)
Induction Over Haskell Data Structures (Full Notes)
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
We will discuss the proof later. For the proof we may use the following properties of lists
xs:[a].
67
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Slide 95
68
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Q(xs) , 8ys:[a].8z : a. [ z 2 ys ! z 2
Slide 97
/ subLst xs ys ]
69
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
P(n) , 8xs:[a].8ys:[a].8z : a.
[ length xs = n ! ( z 2 ys ! z 2
/ subList xs ys ) ]
Observe that
8n : N.P(n) $ 8xs:[a].Q(xs)
Therefore, proving 8n : N.P(n) suffices.
The 1st approach We will discuss the application of the 1st Approach
Application of the Mathematical Induction Principle for 8n : N.8xs : [a].8ys : [a].8z :
a.[length xs = n ! ( z 2 ys ! z 2 / subList xs ys )] gives
8xs : [a].8ys : [a].8z : a.[length xs =0 ! ( z 2 ys ! z 2 / subList xs ys)]
^ 8k : N.[ 8xs : [a].8ys : [a].8z : a.[ length xs = k !
( z 2 ys ! z 2 / subList xs ys) ] ! 8xs : [a].8ys : [a].8z :
a.[ length xs = k+1 ! (z 2 ys ! z 2 / subList xs ys) ] ] !
8n : N.8xs : [a].8ys : [a].8z : a.[ length xs = n ! ( z 2 ys ! z 2 / subList xs ys ) ]
Proof
We can now develop a proof by induction. The proof schema is as follows:
Inductive Step
Take k : N arbitrary. Ind. Hyp: 8xs:[a].8ys:[a].8z : a. [ length xs = k !
( z 2 ys ! z 2/ subList xs ys) ] To show: 8xs:[a].8ys:[a].8z : a. [ length xs = k + 1 !
( z 2 ys ! z 2/ subList xs ys) ]
...
70
We shall use the following properties of length:
We now proceed with the proofs of the base case and the inductive step.
Base Case
To Show: 8xs:[a].8ys:[a].8z : a.[ length xs = 0 ! ( z 2 ys ! z 2
/ subList xs ys) ]
(ass1) length xs = 0
Take arbitrary xs:[a],ys:[a], and z:a. Assume that
(ass2) z 2 ys
To Show: z 2
/ subList xs ys
Then
(3) xs = [] from (ass1) and L1.
(4) subList xs ys = [] from (3) and def of subList.
(5) z2/ subList xs ys from (4) and def of elem.
Note that we did not use (ass2) for this case.
Inductive step
Take k : N arbitrary. Ind. Hyp: 8xs:[a].8ys:[a].8z : a. [ length xs = k ! ( z 2
ys ! z 2 / subList xs ys) ] To show: 8xs:[a].8ys:[a].8z : a. [ length xs = k+1 !
( z 2 ys ! z 2 / subList xs ys) ]
Take arbitrary xs:[a],ys:[a], and z:a.
(ass1) length xs = k + 1
Assume
(ass2) z 2 ys
To Show: z 2
/ subList xs ys
(3) length vs = k
From (ass1) and L2, we obtain that exist values v : a and vs : [a], so that
(4) xs = v:vs
Then (5) z2
/ subList vs ys by (3), (ass2) and Ind Hyp
Continue by case analysis over whether v 2 ys - see next two slides.
1st Case: v 2 ys
Then, (6) subList (v:vs) ys = subList vs ys by case & def subList
(7) z2
/ subList xs ys by (6), (5) & (4). 2nd Case: v 2
/
ys
71
Then (6) subList (v:vs) ys = v:(subList vs ys) by case and definition of subList
(7) z 6= v (ass2) & case.
(8) z2
/ v:(subList vs ys) by (7) , (5) and definition of elem.
(9) z2
/ subList xs ys (6), (5) & (4).
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
72
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 100 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 101 / 403
73
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Base Case
To Show 8ys : [a].8z : a.[ z 2 ys ! z 2 / subList [] ys ]
Slide 102
...
Inductive Step
Take arbitrary v:a, vs:[a]
Inductive Hypothesis:
8ys : [a].8z : a.[ y 2 ys ! y 2
/ subList vs ys ]
To Show: 8ys : [a].8z : a.[ z 2 ys ! z 2/ subList (v:vs) ys ]
...
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 102 / 403
Compare with the proof schema for proof by mathem. induction on the length of the
lists. The one based on structural induction is more succinct.
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Base Case
Base Case
To Show: 8ys : [a].8z : a.[ z 2 ys ! z 2
/ subList [] ys ]
Slide 103
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 103 / 403
74
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Inductive step
Inductive Step
Take arbitrary v:a, vs:[a]
Inductive Hypothesis: 8ys:[a].8z : a. [ z 2 ys ! z 2
/ subList vs ys ]
To Show:
Slide 104
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 104 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 105 / 403
75
Conclusion Reasoning about lists through structural induction is natural.
Our plan
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 106 / 403
In general, universal quantifiers can be swapped and preserve the meaning of an assertion;
i.e., 8x.8y.P (x, y) ! 8y.8x.P (x, y). In the above, we apply the equivalence that 8xs :
[a].8ys : [a].8z : a.[ z 2 ys ! z 2 / subList xs ys ] ! 8ys : [a].8xs : [a].8z : a.
[ z 2 ys ! z 2 / (subList xs ys) ]
76
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
rev :: [ a ] -> [ a ]
rev [] = []
rev ( x : xs ) = rev xs ++ [ x ]
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 107 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
8vs : [a].8v : a. [
8ys : [a]. rev (vs ++ ys) = (rev ys) ++ (rev vs)
!
8ys : [a]. rev ((v:vs) ++ ys) = (rev ys) ++ (rev (v:vs))
]
!
8xs : [a].8ys : [a]. rev (xs ++ ys) = (rev ys) ++ (rev xs)
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 108 / 403
77
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Base Case
To Show 8ys : [a]. rev ([] ++ ys) = (rev ys) ++ (rev [])
Slide 109
...
Inductive Step
Take arbitrary z:a, zs:[a].
Inductive Hypothesis:
8ys:[a]. rev (zs ++ ys) = (rev ys) ++ (rev zs)
To Show: 8ys:[a].rev ((z:zs) ++ ys) = (rev ys) ++ (rev (z:zs))
...
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 109 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Lists Lemmas
us,vs,ws:[a]:
(A) us ++ [] = us
(B) [] ++ us = us
(C) (u : us) ++ vs = u : (us ++ vs)
(D) (us ++ vs) ++ ws = us ++(vs ++ ws)
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 110 / 403
78
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Base Case
Base Case
To Show 8ys : [a]. rev([] ++ ys) = (rev ys) ++(rev [])
Slide 111
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 111 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Inductive Step
Inductive Step
Take arbitrary z : a, zs : [a].
Ind. Hypo: 8ys : [a]. rev (zs ++ ys) = (rev ys) ++ (rev zs)
To show:
Slide 112
8ys’ : [a]. rev ((z : zs) ++ ys’) = (rev ys’) ++(rev (z : zs))
Take arbitrary ys’:[a].
Then, we have:
rev ((z : zs) ++ ys’)
= rev (z : (zs ++ ys’)) by (C)
= (rev (zs ++ ys’)) ++ [z] by definition of rev
= ((rev ys’) ++(rev zs)) ++ [z] by induction hypothesis
= (rev ys’) ++((rev zs) ++ [z]) by (D)
= (rev ys’) ++(rev (z : zs)) by definition of rev
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 112 / 403
79
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
P([]) ! P(x:[]).
Therefore, P(x:[]) holds for all x : a.
P(x:[]) ! P(y:x:[]).
Therefore, P(y:x:[]) holds for all y, x : a.
P(y:x:[]) ! P(z:y:x:[]).
Therefore, P(z:y:x:[]) holds for all z, y, x : a.
...
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 113 / 403
Note that with induction over lists, every element has an infinite number of successors,
(eg 3:[] and 4:[] and 55:[] are all successors of [], while in induction over numbers,
eavery element has only one direct successor, (eg 3 is the unique successor of 2).
80
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 114 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Write the struct. ind. principles for P ✓Tree Int, and for Q ✓Tree a, and
for R ✓Tree [a]:
P(Empty) ^
Slide 115
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 115 / 403
81
Comment But actually, given
data Tree a = Empty | Node ( Tree a ) a ( Tree a )
Do we have
Since the two assertions are equivalent, the question actually does not arise.
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 116 / 403
82
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Consider the Haskell function sum, and its tail-recursive version, sum tr
sum :: [ Int ] -> Int
sum [] = 0
Slide 117
sum i : is = i + sum is
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 117 / 403
83
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 118 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
We cannot prove
Slide 119
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 119 / 403
84
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 120 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Rather than
Slide 121
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 121 / 403
85
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Proving
8is:[Int].8k:Int. k + (sum is) = sum tr is k by
induction on is - base case
Slide 122
Base Case
To Show: 8k:Int. k + (sum []) = sum tr [] k
Take k:Int arbitrary.
To Show: k + sum [] = sum tr [] k
We have
k + (sum []) = k by def. of sum, and arithm
= sum tr [] k by def. of sum tr
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 122 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Proving
8is:[Int].8k:Int. k + (sum is) = sum tr is k by
induction on is - ind step
Inductive Step
Take i:Int and is:[Int] arbitrary.
Slide 123
86
The limits of induction Fermat stated and did not prove that:
xn + y n = z n
has no positive integer solutions for n 3
The format of the theorem suggests the use of induction.
• Inductive Step: Show that if xk +y k = z k has no solutions, then xk+1 +y k+1 = z k+1
has no solutions.
• A proof of the theorem was developed recently, and is not based on induction.
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
!
8t:T.P(t)
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 124 / 403
87
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 125 / 403
88
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Summary
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 126 / 403
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Compare the above with the induction principle for natural numbers:
P(0) ^ 8k : N.[ P(k) ! P(k+1) ] ! 8n : N.P(n)
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 127 / 403
89