Upload
benjamin-sheridan
View
214
Download
0
Tags:
Embed Size (px)
Citation preview
04/10/2304/10/23 11
GC16/3011 Functional ProgrammingLecture 8
Designing Functional Programs (2)
04/10/2304/10/23 22
Contents
Structural induction: example “append”Structural induction: example “append” Passing data between functions: “isort”Passing data between functions: “isort” Modes of recursion: tail recursion and Modes of recursion: tail recursion and
mutual recursionmutual recursion Removing mutual recursionRemoving mutual recursion Lazy evaluation: infinite listsLazy evaluation: infinite lists
04/10/2304/10/23 33
Induction on Lists: “append”
The “append” function takes two lists of anything and The “append” function takes two lists of anything and returns a single list consisting of all the elements of the returns a single list consisting of all the elements of the first list, followed by all the element of the second listfirst list, followed by all the element of the second list
Type:Type:append :: ([*], [*]) -> [*]
Possible Induction hypotheses:append (xs, (y:ys))
OR: append ((x:xs), ys) OR: append (xs, ys)to help define the general case:
append ((x:xs), (y:ys)) = ????
04/10/2304/10/23 44
Induction on Lists: “append”
Think about what each possible induction hypothesis Think about what each possible induction hypothesis would give youwould give you
For example, if we want to define the general case for For example, if we want to define the general case for append ([1,2,3], [4,5,6]):append ([1,2,3], [4,5,6]):
append(xs, (y:ys)) gives us [2,3,4,5,6] – does that help?append(xs, (y:ys)) gives us [2,3,4,5,6] – does that help?
append((x:xs),ys) gives us [1,2,3,5,6] – does that help?append((x:xs),ys) gives us [1,2,3,5,6] – does that help?
append (xs, ys) gives us [2,3,5,6] – does that help?append (xs, ys) gives us [2,3,5,6] – does that help?
04/10/2304/10/23 55
Induction on Lists: “append”
Answer: use append (xs, (y:ys)) as the induction Answer: use append (xs, (y:ys)) as the induction hypothesis. Thus, there is only one parameter of hypothesis. Thus, there is only one parameter of recursion. The general case is:recursion. The general case is:
append ((x:xs), (y:ys)) = x : (append (xs, (y:ys))
Or, simply:
append ((x:xs), any) = x : (append (xs, any))
04/10/2304/10/23 66
Induction on Lists: “append”
Base case (for parameter of recursion):Base case (for parameter of recursion):
append ([], (y:ys)) = ???? We choose the answer to be (y:ys)
append ([], (y:ys)) = (y:ys)
Or, simply:
append ([], any) = any
04/10/2304/10/23 77
Induction on Lists: “append”
Final solution:Final solution:
append :: ([*], [*]) -> [*]
append ([], any) = any
append ((x:xs), any) = x : (append (xs, any))
04/10/2304/10/23 88
Passing data between functions
A functional program usually contains A functional program usually contains several (many) functionsseveral (many) functions
Focus on how data passes between those Focus on how data passes between those functionsfunctions
Example: insertion sort “isort”Example: insertion sort “isort”
04/10/2304/10/23 99
Insertion Sort (specification)
Define “sorted list”Define “sorted list” An empty list is already sortedAn empty list is already sorted A singleton list is already sortedA singleton list is already sorted The list (x:xs) is sorted if The list (x:xs) is sorted if
x is less than all items in xs, ANDx is less than all items in xs, AND xs is sortedxs is sorted
NB only lists of numbersNB only lists of numbers
04/10/2304/10/23 1010
Insertion Sort (strategy)
Start with two lists A and BStart with two lists A and B A is the input listA is the input list B is initially emptyB is initially empty One at a time, move an element from A to BOne at a time, move an element from A to B Ensure that at all times B is sortedEnsure that at all times B is sorted
We will need a function that can We will need a function that can insertinsert a number a number into a sorted list and return a sorted listinto a sorted list and return a sorted list
04/10/2304/10/23 1111
Insertion Sort (design)
The list B is an accumulatorThe list B is an accumulator So use accumulative recursionSo use accumulative recursion
Top-down approach: assume the function Top-down approach: assume the function “insert” exists and design the rest of the “insert” exists and design the rest of the program first (leap of faith!)program first (leap of faith!)
Then design “insert”Then design “insert”
04/10/2304/10/23 1212
Insertion sort (code 1)
|| comments…|| comments…
isort :: [num] -> [num]isort :: [num] -> [num]
isort any = xsort any []isort any = xsort any []
|| comments…|| comments…
xsort :: [num] -> [num] -> [num]xsort :: [num] -> [num] -> [num]
xsort [] sorted = sortedxsort [] sorted = sorted
xsort (x:xs) sorted = xsort xs (xsort (x:xs) sorted = xsort xs (insertinsert x sorted) x sorted)
04/10/2304/10/23 1313
Insertion sort (code 2)
Code for “insert”:Code for “insert”:
|| comments…|| comments…
insert :: num -> [num] -> [num]insert :: num -> [num] -> [num]
insert x [] = [x]insert x [] = [x]
insert x (y:ys) = (x:(y:ys)), if (x<y)insert x (y:ys) = (x:(y:ys)), if (x<y)
= ????= ????
04/10/2304/10/23 1414
Insertion sort (code 3)
Use induction hypothesis: assume that “insert x Use induction hypothesis: assume that “insert x ys” correctly inserts x into the list ys and produces ys” correctly inserts x into the list ys and produces the correct sorted list as a result:the correct sorted list as a result:
insert :: num -> [num] -> [num]insert :: num -> [num] -> [num]
insert x [] = [x]insert x [] = [x]
insert x (y:ys) = (x:(y:ys)), if (x<y)insert x (y:ys) = (x:(y:ys)), if (x<y)
= (y : (insert x ys)), otherwise= (y : (insert x ys)), otherwise
04/10/2304/10/23 1515
Modes of recursion: tail recursion
mylast :: [*] -> *mylast :: [*] -> *
mylast [] = error “no last item of empty list”mylast [] = error “no last item of empty list”
mylast (x:[]) = xmylast (x:[]) = x
mylast (x:xs) = mylast xsmylast (x:xs) = mylast xs
04/10/2304/10/23 1616
Modes of recursion: mutual recursion
nasty :: [char] -> [char]nasty :: [char] -> [char]nasty [] = []nasty [] = []nasty (‘(‘:rest) = nasty (‘(‘:rest) = xnastyxnasty rest restnasty (x:xs) = (x : (nasty xs))nasty (x:xs) = (x : (nasty xs))
xnasty :: [char] -> [char]xnasty :: [char] -> [char]xnasty [] = error “missing end bracket”xnasty [] = error “missing end bracket”xnasty (‘)’:rest) = xnasty (‘)’:rest) = nastynasty rest restxnasty (x:xs) = xnasty xsxnasty (x:xs) = xnasty xs
04/10/2304/10/23 1717
Removing mutual recursion
skip :: [char] -> [char]skip :: [char] -> [char]skip [] = []skip [] = []skip (‘(‘: rest) = skip (doskip rest)skip (‘(‘: rest) = skip (doskip rest)skip (x:rest) = (x : (skip rest))skip (x:rest) = (x : (skip rest))
doskip :: [char] -> [char]doskip :: [char] -> [char]doskip [] = error “missing end bracket”doskip [] = error “missing end bracket”doskip (‘)’:rest) = restdoskip (‘)’:rest) = restdoskip (x:xs) = doskip xsdoskip (x:xs) = doskip xs
04/10/2304/10/23 1818
Lazy evaluation: infinite lists
Evaluate fst (24, (37 / 0))Evaluate fst (24, (37 / 0)) Remember definition of fst:Remember definition of fst:
fst :: (*,**) -> *fst :: (*,**) -> *
fst (x,y) = xfst (x,y) = x
What does this function do? :-What does this function do? :-f x = (x : (f (x+1)))f x = (x : (f (x+1)))
04/10/2304/10/23 1919
Infinite lists (2)
Some forms of “bad” recursion may NOT Some forms of “bad” recursion may NOT create an infinite loop because they are create an infinite loop because they are evaluated ONLY AS FAR AS evaluated ONLY AS FAR AS NECESSARY:NECESSARY:f :: num -> [num]f :: num -> [num]
f x = (x : (f (x + 1))f x = (x : (f (x + 1))
main = hd (tl (f 34))main = hd (tl (f 34))
04/10/2304/10/23 2020
Infinite lists (3)
ones = (1 : ones)ones = (1 : ones)
main = hd (tl (tl ones))main = hd (tl (tl ones))
04/10/2304/10/23 2121
Summary
Structural induction: example “append”Structural induction: example “append” Passing data between functions: example Passing data between functions: example
“isort”“isort” Modes of recursion: tail recursion and Modes of recursion: tail recursion and
mutual recursionmutual recursion Removing mutual recursionRemoving mutual recursion Lazy evaluation: infinite listsLazy evaluation: infinite lists