0% found this document useful (0 votes)
26 views23 pages

Induction Over Haskell Data Structures (Full Notes)

Uploaded by

francoispoh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
26 views23 pages

Induction Over Haskell Data Structures (Full Notes)

Uploaded by

francoispoh
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 23

1.

3 Structural induction over Haskell data types

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Week 4 – First Challenge


Consider following functions:
check :: [ a ] -> Bool
check [] = true
check x : xs = check1 ( x : xs ) []
Slide 93

check1 :: [ a ] -> [ a ] -> Bool


check1 [] zs = false
check1 ( y : ys ) zs | ( y : ys )== zs = true
| ys == zs = true
| otherwise = check1 ys ( y : zs )

Palindrome ✓ [a] is defined as


Palindrome(xs) , 9ys : [a], y : a. [ xs = ys ++ (rev ys) _
xs = ys ++ y ++ (rev ys) ]
Show that
(⇤) 8xs : [a]. [ check xs ! Palindrome(xs) ]
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 93 / 403

We will discuss the proof later. For the proof we may use the following properties of lists
xs:[a].

(A) xs = rev(rev xs)

(B) P alindrome(xs) ! P alindrome(rev xs)

(C) rev (x:xs) = (rev xs) ++ x

67
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Week 4 – Second Challenge


Remember the cactus/beetle example:
A cactus consists of a tree, whose nodes have arbitrary numbers of
children.
When the beetle eats a leaf lf , then lf is removed, and if lf is not a child
Slide 94

of the root, then, the cactus grows back as follows:


Let Tlf be the subtree starting at parent(lf ) where lf has been removed.
Add k copies of Tlf under parent(parent(lf )), where k is an arbitrary
natural number.
The cactus is consumed when it consists of the root only.

How do we formulate that all cacti can be consumed? Can we prove


it?
How do we formulate that all cacti will be consumed? Can we prove
it?
Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 94 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types
Slide 95

Structural induction over Haskell data types

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 95 / 403

68
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Structural induction - motivation

Consider the following Haskell functions


elem :: Eq a = > a -> [ a ] -> Bool
elem x [] = False
elem x ( y : ys ) = x == y || elem x ys
Slide 96

subList :: Eq a = > [ a ] -> [ a ] -> [ a ]


subList [] ys = []
subList ( x : xs ) ys
| elem x ys = subList xs ys
| otherwise = x :( subList xs ys )
and the specification
8xs:[a].8ys:[a].8z : a. [ z 2 ys ! z 2
/ subList xs ys ]
where z 2 ys is short for elem z ys, and z 2
/ ys is short for ¬(elem z ys).

In other words: sublist xs ys removes all elements of ys from xs.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 96 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Structural induction - motivation, continued

We want to prove 8xs:[a].Q(xs), where, Q is defined as:

Q(xs) , 8ys:[a].8z : a. [ z 2 ys ! z 2
Slide 97

/ subLst xs ys ]

Can we use induction? Note that Q is not defined over numbers.

1st Approach Map lists to numbers,


express Q ✓ [a], through an equivalent P ✓ N.
2nd Approach Use a new principle: structural induction.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 97 / 403

69
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

1st Approach - mapping lists onto N

We can map lists to numbers through the length function.


Define P(n) as:
Slide 98

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.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 98 / 403

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:

Base Case To Show: 8xs:[a].8ys:[a].8z : a.[ length xs = 0 ! ( z 2 ys ! z 2


/
subList xs ys) ]
...

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:

L1 8xs : [a]. ( length xs = 0 ! xs = []. )

L2 8xs : [a].8k : N. [ length xs = k+1 ! 9v : a.9vs : [a].[ length vs = k ^ xs =


v : vs] ].

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

1st approach – conclusions

It is possible to reason about lists using math. induction. But this


reasoning is indirect: In particular, length is unrelated to P.
The math. induct based proof requires lemmas:
Slide 99

L1: 8xs : [a]. [ length xs = 0 ! xs = [] ]


L2: 8xs : [a].8k : N.
[ length xs = k +1 ! 9v : a.9vs : [a].[ length vs = k ^ xs = v : vs] ].
How do we prove L1 and L2?
Therefore, we need something better.
In math. induct. step, we argue that a property is ”inherited” from
”predecessor” to their ”successor”. E.g., 4 is a ”successor” of 3.
Can we generalize the concept of ”predecessor” and ”successor”?
Can we see 10:44:33:[] as successor of 44:33:[]?

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 99 / 403

72
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Structural Induction Principle over lists


Slide 100

For any type T, and P ✓ [T]:

P([]) ^ 8vs:[T].8v:T.[ P(vs) ! P(v:vs) ] ! 8xs:[T].P(xs)

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 100 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Structural induction principle applied to xs for the


subList property

Structural induction principle on xs for


8xs : [a].8ys : [a].8z : a.[ z 2 ys ! z 2
/ subList xs ys ]
Slide 101

8ys : [a].8z : a.[ z 2 ys ! z 2 / subList [] ys ]


^
8vs : [a].8v : a. [
8ys : [a].8z : a.[ z 2 ys ! z 2/ subList vs ys ]
!
8ys : [a].8z : a.[ z 2 ys ! z 2
/ subList (v:vs) ys ]
]
!
8xs : [a].8ys : [a].8z : a.[ z 2 ys ! z 2 / subList xs ys ]

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 101 / 403

73
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Proving the subList property by str. ind. - schema

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

Take arbitrary ys: [a], and z: a.


Assume (ass1) z 2 ys
To Show: z 2 / subList [] ys
We have
(1) subList [] ys = [] by def. of subList
(2) z 2 / subList [] ys by (1) and def. of elem

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

8ys’:[a].8z’ : a. [ z’ 2 ys’ ! z’ 2 / subList (v:vs) ys’ ]


Take arbitrary ys’:[a], and z’:a.
Assume
(ass1) z’ 2 ys’
To Show: z’ 2
/ subList (v:vs) ys’
Then
(IH’) z’ 2 ys’ ! z’ 2/ subList vs ys’ by Ind Hyp
(1) z’ 2
/ subList vs ys’ by (ass1), and (IH’)
Continue on next slide

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 104 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Inductive step - continued

What we have so far:


(ass1) z’ 2 ys’
(1) z’ 2
/ subList vs ys’
To Show: z’ 2 / subList (v:vs) ys’.
Slide 105

1st Case: v 2 ys’


Then
(2) subList (v:vs) ys’ = subList vs ys’ by case & def subList
(3) z’ 2/ subList (v:vs) ys’ by (1) & (2).

2nd Case: v 2/ ys’


Then
(2) subList (v:vs) ys’ = v:(subList vs ys’) case & def subList
(3) z’ 6= v (ass1) & case.
(4) z’ 2/ subList (v:vs) ys’ by (1), (2), (3)
and & def. elem.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 105 / 403

75
Conclusion Reasoning about lists through structural induction is natural.

Our plan

Discuss one more example reasoning about lists.


Reason about any user defined Haskell data type.

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Variation: Structural induction principle over ys applied to the subList


property

Applying structural induction on ys for


8xs : [a].8ys : [a].8z : a.[ z 2 ys ! z 2
/ subList xs ys ]
Slide 106

8xs : [a].8z : a.[ z 2 [] ! z 2 / subList xs [] ]


^
8vs : [a].8v : a. [
8xs : [a].8z : a.[ z 2 vs ! z 2/ subList xs vs ]
!
8xs : [a].8z : a.[ z 2 (v:vs) ! z 2/ subList xs (v:vs) ]
]
!
8xs : [a].8ys : [a].8z : a.[ z 2 ys ! z 2 / subList xs ys ]

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

another example, rev

Consider the following Haskell function:


Slide 107

rev :: [ a ] -> [ a ]
rev [] = []
rev ( x : xs ) = rev xs ++ [ x ]

Consider the assertion:


SPEC 1: 8xs: [a].8ys: [a]. rev (xs ++ ys) = (rev ys) ++ (rev xs)

We will prove SPEC 1 by structural induction over xs.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 107 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Lists Struct. induction principle applied to SPEC 1

8ys : [a]. rev ([] ++ ys) = (rev ys) ++ (rev [])


^
Slide 108

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

Proving SPEC 1 by str. ind. - schema

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

We use the following properties of ++ and : for arbitrary u:a,


Slide 110

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

Take arbitrary ys:[a].


Then, we have
rev([] ++ ys)
= rev ys by (B)
= (rev ys) ++ [] by (A)
= (rev ys) ++(rev []) by definition of rev

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

Why does induction over lists work?

Intuitively, and informally


Base case: P([]) holds.
Inductive Step: P(xs) ! P(x:xs) for all x : a, xs : [a].
Slide 113

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.
...

And so, P(xs) holds for all xs : [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

Induction over arbitrary Haskell data structures

data Nat = Zero | Succ Nat


P(Zero) ^ 8n:Nat.[ P(n) ! P(Succ n) ] ! 8n:Nat.P(n)
Slide 114

data Tree a = Empty | Node ( Tree a ) a ( Tree a )


P(Empty) ^ 8t1,t2:Tree T.8x:T.[ P(t1) ^ P(t2) ! P(Node t1 x t2 ) ]
! 8t:Tree T.P(t)

data BExp = Tr | Fl | BNt BExp | BAnd BExp BExp


P(Tr) ^ P(Fl) ^ 8b:BExp.[ P(b) ! P(BNt b) ] ^
8b1,b2:BExp.[ P(b1) ^ P(b2) ! P(BAnd b1 b2) ] ! 8b:BExp.P(b)

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 114 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Structural Induction for di↵erent kinds of trees

Write the struct. ind. principles for P ✓Tree Int, and for Q ✓Tree a, and
for R ✓Tree [a]:
P(Empty) ^
Slide 115

8t1,t2:Tree Int.8i:Int.[ P(t1) ^ P(t2) ! P(Node t1 i t2) ]


! 8t:Tree Int. P(t)
Q(Empty) ^
8t1,t2:Tree a.8x:a.[ Q(t1) ^ Q(t2) ! Q(Node t1 x t2) ] ]
! 8t : Tree a. Q(t)
R(Empty) ^
8t1,t2:Tree [a].8as:[a]. [ R(t1) ^ R(t2) ! R(Node t1 as t2) ]
! 8t : Tree[a]. R(t)

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

[ P (Empty) ^ 8t1,t2:Tree T.8x:T.[ P (t1) ^ P (t2) ! P (Node t1 x t2) ] ]


!
8t:Tree T.P (t)

or, should we have, instead

[ P (Empty) ^ 8t1,t2:Tree T.[ P (t1) ^ P (t2) ! 8x:T.P (Node t1 x t2) ] ]


!
8t:Tree T.P (t)

Since the two assertions are equivalent, the question actually does not arise.

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Two Proof strategies


Slide 116

We will conclude this section by discussing two strategies that appear


often when writing proofs.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 116 / 403

82
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

... When the proof does not go through ...

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

sum_tr :: [ Int ] -> Int -> Int


sum_tr [] k = k
sum_tr ( i : is ) k = sum_tr is ( i + k )
Prove that

8is:[Int]. sum is = sum tr is 0

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 117 / 403

Proving 8is:[Int]. sum is = sum tr is 0 by induction on is - base case


Base Case To Show sum [] = sum tr [] 0
sum []
We have = 0 by def. of sum
= sum tr [] 0 by def. of sum tr
The inductive step is in the slides.

83
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Inductive step for 8is:[Int]. sum is = sum tr is 0

Take i: Int and is:[Int] arbitrary.


Inductive Hypothesis: sum is = sum tr is 0
Slide 118

To Show: sum (i:is) = sum tr (i:is) 0

By applying definitions we obtain


sum (i:is) = i + sum is by def. of sum
= i + sum tr is 0 by ind. hypo.
??? ???
= sum tr is i ???
= sum tr (i:is) 0 by def. of sum tr

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 118 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

When the proof does not go through ... - two


approaches

We cannot prove
Slide 119

8is:[Int]. sum is = sum tr is 0


directly by induction.
Such situations appear very often in proofs.

There are two approaches to solving such problems:


1st Strategy: Invent an Auxiliary Lemma
2nd Strategy: Strengthen the original property

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 119 / 403

84
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

1st Strategy: Invent an auxiliary lemma

We revisit the Inductive step from the proof of


8is:[Int]. sum is = sum tr is 0.
Inductive step
Slide 120

Take i: Int, and is:[Int] arbitrary.


Inductive Hypothesis sum is = sum tr is 0
To Show: sum (i:is) = sum tr (i:is) 0
We have
sum (i:is) = i + sum is by def. of sum
= i + (sum tr is 0) by ind. hypo.
= sum tr is (i+0) by Lemma ZZ
= sum tr (i:is) 0 by def. of sum tr
Lemma ZZ
8i:Int.8k:Int.8is:[Int]. i + (sum tr is k) = sum tr is (i+k)

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 120 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

2nd Strategy: Proving a stronger property

Rather than
Slide 121

(⇤) 8is:[Int]. sum is = sum tr is 0


We will prove a stronger property

(⇤⇤) 8k:Int.8is:[Int]. k + (sum is) = sum tr is k

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

Inductive Hypothesis: 8 m:Int. m+(sum (is)) = sum tr (is) m


To Show: 8 m’:Int. m’+(sum (i:is)) = sum tr (i:is) m’
Take m’:Int arbitrary.
To Show: m’+sum (i:is)= sum tr (i:is) m’
m’ + (sum (i:is)) = (m’+i) + (sum is) by def. sum, arithm
= sum tr is (m’+i) by ind. hyp.
= sum tr (i:is) m’ by def. of sum tr

Note: We instantiated the induction hypothesis by replacing m by m’+i.


Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 123 / 403

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.

• Base case: it has been proved that x3 + y 3 = z 3 has no solutions.

• 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.

• Nobody has been able to do that.

• 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

More Induction Principles – mutual recursion


Thank you to Tiberiu-Andrei Georgescu

data T = C1 [ Int ] | C2 Int T

8is:[Int]. P(C1 is) ^ 8i:Int.8t:T.[ P(t) ! P(C2 i t) ]


Slide 124

!
8t:T.P(t)

data Reds = BaseR | Red Greens


data Greens = BaseG | Green Reds

P(BaseR) ^ 8g:Greens. [ Q(g) ! P(Red g) ] ^


Q(BaseG) ^ 8r:Reds. [ P(r) ! Q(Green r) ]
!
8r:Reds.P(r) ^ 8g:Greens.Q(g)

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 124 / 403

An alternative way to express the inductive principle, proposed by Tiberiu-Andrei Georgescu,


is as follows:

P (BaseR) ^ P (Red(BaseG)) ^ 8r:Reds. [ P (r) ! P (Red(Green(r))) ]


! 8r:Reds.P (r)

87
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

The cactus revisited

data Cactus = Root Tree


data Tree = Leaf | Node Trees
Slide 125

data Trees = Empty | Cons Tree Trees

Express an inductive principle for Tree.


P(Leaf) ^
8ts:Trees. [ Q(ts) ! P(Node ts) ] ^
Q(Empty) ^
8t:Tree.8ts:Trees. [ P(t) ^ Q(ts) ! Q(Cons t ts) ]
!
8t:Tree.P(t) ^ 8ts:Trees.Q(ts)

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 125 / 403

A slightly weaker inductive principle is the following:


P (Leaf) ^ P (Node []) ^ 8ts:Trees.8t:Tree. [ P (t)^P (Node ts) !
P (Node t:ts) ] ! 8t:Tree.P (t)

Consider now this, equivalent definition of the cactus:

data Cactus = Root Tree


data Tree = Leaf | Node [ Tree ]

We can describe the inductive principle for Tree as follows:


P (Leaf) ^ 8ts:Trees. [ 8t : Tree.8ts1, ts2 : Trees.[ ts =
ts1 ++[t] ++ ts2 ! P (t) ] ! P (Node(ts)) ] ! 8t:Tree.P (t)

88
Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Summary

Inductively defined Haskell data type give rise to an induction


principle.
Inductive Principle leads to Proof Schema
Slide 126

Sometimes swapping quantifiers in assertions allows for equivalent properties


whose proof is easier.
Sometimes we need to strengthen the lemmas – c.f. slides earlier and
assessed PMT.
Sometimes we need to invent auxiliary lemmas – c.f. slides earlier and class
tutorial.
Be precise with the scope of universally/existentially quantified variables –
c.f. slides earlier and assessed PMT.

Drossopoulou & Wheelhouse (DoC) CO141: Reasoning about Programs 126 / 403

Part I: Reasoning About Haskell Programs Structural induction over Haskell data types

Summary: common induction principles

Some common structural induction principles:


P(Zero) ^ 8n:Nat.[ P(n) ! P(Succ n) ] ! 8n:Nat.P(n)
P(Empty) ^
Slide 127

8t1,t2:Tree T.8x:T.[ P(t1) ^ P(t2) ! P(Node t1 x t2) ]


! 8t:Tree T.P(t)
P([]) ^ 8xs:[T].8x:T.[ P(xs) ! P(x:xs) ]
! 8xs:[T].P(xs)

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

You might also like