Download as pdf or txt
Download as pdf or txt
You are on page 1of 7

Prof. Dr.

Ralf Hinze TU Kaiserslautern


M.Sc. Sebastian Schloßer
Fachbereich Informatik
AG Programmiersprachen

Functional Programming: Exercise 5


Sheet published: Thursday, June 2nd
Exercise session: Thursday, June 9th, 12:00

Exercise 5.1 (Induction). Consider the following program for binary search trees:

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


insert :: Ord a ⇒ a → Tree a → Tree a
insert x Leaf = Node Leaf x Leaf
insert x (Node l e r )
|x 6e = Node (insert x l ) e r
| otherwise = Node l e (insert x r )

A binary tree is a search tree if and only if for each Node l e r , all elements in l are 6 e
and all elements in r are >e:

isSearchTree :: Ord a ⇒ Tree a → Bool


isSearchTree Leaf = True
isSearchTree (Node l e r ) = allT (\x → x 6 e) l
&& allT (\x → x > e) r
&& isSearchTree l
&& isSearchTree r
allT :: (a → Bool ) → Tree a → Bool
allT Leaf = True
allT f (Node l e r ) = f e && allT f l && allT f r

Using a structural induction on the Tree data type, show that

1
a) ∀t, y, f f y && allT f t =⇒ allT f (insert y t)

Base case: t = Leaf

∀y, f f y && allT f Leaf =⇒ allT f (insert y Leaf )


= { def. insert }
∀y, f f y && allT f Leaf =⇒ allT f (Node Leaf y Leaf )
= { def. allT }
∀y, f f y && allT f Leaf =⇒ f y && allT f Leaf && allT f Leaf

Induction step: t = Node l e r


Induction Hypothesis 1: ∀y, f f y && allT f l =⇒ allT f (insert y l )
Induction Hypothesis 2: ∀y, f f y && allT f r =⇒ allT f (insert y r )
Need to show: ∀y, f f y && allT f (Node l e r ) =⇒ allT f (insert y (Node l e r ))
Case y 6 e

∀y, f f y && allT f (Node l e r ) =⇒ allT f (insert y (Node l e r ))


= { def. insert, case y 6 e }
∀y, f f y && allT f (Node l e r ) =⇒ allT f (Node (insert y l ) e r )
= { def. allT }
∀y, f f y && f e && allT f l && allT f r =⇒ f e && allT f (insert y l ) && allT f r
⇐= { Induction Hypothesis 1 }
∀y, f f y && f e && allT f l && allT f r =⇒ f e && f y && allT f l && allT f r

Case y > e

∀y, f f y && allT f (Node l e r ) =⇒ allT f (insert y (Node l e r ))


= { def. insert, case y > e }
∀y, f f y && allT f (Node l e r ) =⇒ allT f (Node l e (insert y r ))
= { def. allT }
∀y, f f y && f e && allT f l && allT f r =⇒ f e && allT f l && allT f (insert y r )
⇐= { Induction Hypothesis 2 }
∀y, f f y && f e && allT f l && allT f r =⇒ f e && allT f l && f y && allT f r

2
b) ∀t, y isSearchTree t =⇒ isSearchTree (insert y t)

Base case: t = Leaf

∀y isSearchTree Leaf =⇒ isSearchTree (insert y Leaf )


= { def. insert }
∀y isSearchTree Leaf =⇒ isSearchTree (Node Leaf y Leaf )
= { def. isSearchTree }
∀y isSearchTree Leaf =⇒ allT (\x → x 6 y) Leaf && allT (\x → x > y) Leaf
&& isSearchTree Leaf && isSearchTree Leaf
= { def. allT , def. isSearchTree }
∀y isSearchTree Leaf =⇒ True && True && True && True

Induction step: t = Node l e r


Induction Hypothesis 1: ∀y isSearchTree l =⇒ isSearchTree (insert y l )
Induction Hypothesis 2: ∀y isSearchTree r =⇒ isSearchTree (insert y r )
Need to show: ∀y isSearchTree (Node l e r ) =⇒ isSearchTree (insert y (Node l e r ))
Case y 6 e

∀y isSearchTree (Node l e r ) =⇒ isSearchTree (insert y (Node l e r ))


= { def. insert, case y 6 e }
∀y isSearchTree (Node l e r ) =⇒ isSearchTree (Node (insert y l ) e r )
= { def. isSearchTree }
∀y allT (\x → x 6 e) l =⇒ allT (\x → x 6 e) (insert y l )
&& allT (\x → x > e) r && allT (\x → x > e) r
&& isSearchTree l && isSearchTree (insert y l )
&& isSearchTree r && isSearchTree r
⇐= { Induction Hypothesis 1 }
∀y allT (\x → x 6 e) l =⇒ allT (\x → x 6 e) (insert y l )
&& allT (\x → x > e) r && allT (\x → x > e) r
&& isSearchTree l && isSearchTree l
&& isSearchTree r && isSearchTree r
⇐= { using part a) }
∀y allT (\x → x 6 e) l =⇒ y 6 e && allT (\x → x 6 e) l
&& allT (\x → x > e) r && allT (\x → x > e) r
&& isSearchTree l && isSearchTree l
&& isSearchTree r && isSearchTree r
⇐= { case y 6 e }

3
Case y > e

∀y isSearchTree (Node l e r ) =⇒ isSearchTree (insert y (Node l e r ))


= { def. insert, case y > e }
∀y isSearchTree (Node l e r ) =⇒ isSearchTree (Node l e (insert y r ))
= { def. isSearchTree }
∀y allT (\x → x 6 e) l =⇒ allT (\x → x 6 e) l
&& allT (\x → x > e) r && allT (\x → x > e) (insert y r )
&& isSearchTree l && isSearchTree l
&& isSearchTree r && isSearchTree (insert y r )
⇐= { Induction Hypothesis 2 }
∀y allT (\x → x 6 e) l =⇒ allT (\x → x 6 e) l
&& allT (\x → x > e) r && allT (\x → x > e) (insert y r )
&& isSearchTree l && isSearchTree l
&& isSearchTree r && isSearchTree r
⇐= { using part a) }
∀y allT (\x → x 6 e) l =⇒ allT (\x → x 6 e) l
&& allT (\x → x > e) r && y > e && allT (\x → x > e) r
&& isSearchTree l && isSearchTree l
&& isSearchTree r && isSearchTree r
⇐= { case y > e }

Annotate each step of your proof with a justification (for example “def. insert”).

4
Exercise 5.2 (Fusion). Like foldr captures a common recursion scheme (canned recur-
sion), fusion captures a common induction scheme (canned induction).

f ( foldr (/) e xs) = foldr (J) (f e) xs ⇐= f (a / b) = a J f b


f ◦ foldr (/) e = foldr (J) (f e) ⇐= f ◦ (a/) = (a J) ◦ f

Many functions can be expressed in terms of foldr . This allows us to use fusion with those
functions, too. For example:

x ++ y = foldr (:) y x
and = foldr (&&) True
concat = foldr (++) [ ]
length = foldr (\x n → 1 + n) 0
map f = foldr (\x xs → f x : xs) [ ]
or = foldr (||) False
sum = foldr (+) 0

a) Using fusion, prove that 2 ∗ (foldr (+) 0 xs) = foldr (\a x → 2 ∗ a + x ) 0 xs.

2 ∗ (foldr (+) 0 xs) = foldr (\a x → 2 ∗ a + x ) 0 xs


⇐= { foldr fusion }
2 ∗ 0 = 0 ∧ 2 ∗ (a + b) = 2 ∗ a + (2 ∗ b)
⇐⇒ { distributive law }
True

b) Prove the foldr -map fusion law:

foldr (.) e ◦ map f = foldr (\a b → f a . b) e

Do not use induction. Instead, apply fusion making use of the fact that map can be
defined in terms of foldr .

foldr (.) e ◦ map f = foldr (\a b → f a . b) e


⇐⇒ { map f = foldr (\x xs → f x : xs) [ ] }
foldr (.) e ◦ foldr (\x xs → f x : xs) [ ] = foldr (\a b → f a . b) e
⇐= { foldr fusion }
foldr (.) e [ ] = e ∧ (foldr (.) e) ◦ (\xs → f a : xs) = (\b → f a . b) ◦ (foldr (.) e)
⇐⇒ { universal property for foldr , function composition, extensionality }
foldr (.) e (f a : xs) = f a . (foldr (.) e xs)
⇐⇒ { universal property for foldr }
True

5
c) Use foldr -map fusion to prove that length = sum ◦ map (const 1).
Hint: Substitute length and sum with the definitions given above.

sum ◦ map (const 1) = length


⇐⇒ { sum = foldr (+) 0, length = foldr (\x n → 1 + n) 0 }
foldr (+) 0 ◦ map (const 1) = foldr (\x n → 1 + n) 0
⇐= { foldr -map fusion }
1 + n = const 1 x + n
⇐⇒ { def. const }
1+n =1+n
⇐⇒
True

d) Again prove that length xs = sum (map (const 1) xs), this time by doing a structural
induction on the list data type. Use the definitions:

length [ ] =0
length (x : xs) = 1 + length xs
sum [] =0
sum (x : xs) = x + sum xs
map [ ] = []
map f (x : xs) = f x : map f xs
const c =c

Base case: [ ]

sum (map (const 1) [ ])


= { def. map }
sum [ ]
= { def. sum }
0
= { def. length }
length [ ]

6
Induction step: x : xs
Induction Hypothesis: length xs = sum (map (const 1) xs)

sum (map (const 1) (x : xs))


= { def. map }
sum (const 1 x : map (const 1) xs)
= { def. sum }
const 1 x + sum (map (const 1) xs)
= { induction hypothesis }
const 1 x + length xs
= { def. const }
1 + length xs
= { def. length }
length (x : xs)

You might also like