Recursion on Lists Lecture 5, Programmeringsteknik del A.

Slides:



Advertisements
Similar presentations
Formal Models of Computation Part II The Logic Model
Advertisements

Introduction A function is called higher-order if it takes a function as an argument or returns a function as a result. twice :: (a  a)  a  a twice.
Modern Programming Languages, 2nd ed.
Comp 205: Comparative Programming Languages Functional Programming Languages: More Haskell Nested definitions Lists Lecture notes, exercises, etc., can.
0 PROGRAMMING IN HASKELL Chapter 5 - List Comprehensions.
0 PROGRAMMING IN HASKELL Chapter 7 - Higher-Order Functions.
Higher-Order Functions Koen Lindström Claessen. What is a “Higher Order” Function? A function which takes another function as a parameter. Examples map.
0 PROGRAMMING IN HASKELL Chapter 4 - Defining Functions.
0 PROGRAMMING IN HASKELL Chapter 6 - Recursive Functions Most of this should be review for you.
0 PROGRAMMING IN HASKELL Chapter 6 - Recursive Functions.
Functional Design and Programming Lecture 4: Sorting.
Advanced Programming Andrew Black and Tim Sheard Lecture 4 Intro to Haskell.
0 PROGRAMMING IN HASKELL Chapter 3 - Types and Classes.
Cse536 Functional Programming 1 7/14/2015 Lecture #2, Sept 29, 2004 Reading Assignments –Begin Chapter 2 of the Text Home work #1 can be found on the webpage,
Comp 205: Comparative Programming Languages Functional Programming Languages: More Lists Recursive definitions List comprehensions Lecture notes, exercises,
0 PROGRAMMING IN HASKELL Typeclasses and higher order functions Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and.
1 COMP313A Programming Languages Functional Programming (7)
Functional Programming Lecture 4 - More Lists Muffy Calder.
Tuples and Lists Lecture 3, Programmeringsteknik del A.
PrasadCS7761 Haskell Data Types/ADT/Modules Type/Class Hierarchy Lazy Functional Language.
0 PROGRAMMING IN HASKELL Chapter 7 - Defining Functions, List Comprehensions.
C++ Programming: From Problem Analysis to Program Design, Second Edition Chapter 19: Searching and Sorting.
Advanced Functional Programming 2009 Ulf Norell (lecture by Jean-Philippe Bernardy)
A Second Look At ML 1. Outline Patterns Local variable definitions A sorting example 2.
Overview of the Haskell 98 Programming Language
What is a Type? A type is a name for a collection of related values. For example, in Haskell the basic type Bool contains the two logical values: True.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: Higher-order Functions Dr. Hyunyoung Lee.
1 CS 457/557: Functional Languages Lists and Algebraic Datatypes Mark P Jones Portland State University.
Kyung-Goo Doh Hanyang University - ERICAComputer Science & Engineering Functional Programming / Imperative Programming CSE215 Fundamentals of Program Design.
0 PROGRAMMING IN HASKELL Chapter 4 - Defining Functions.
Lee CSCE 314 TAMU 1 CSCE 314 Programming Languages Haskell: More on Functions and List Comprehensions Dr. Hyunyoung Lee.
Chapter SevenModern Programming Languages1 A Second Look At ML.
0 PROGRAMMING IN HASKELL Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and a few other sources) Odds and Ends,
Haskell Chapter 4. Recursion  Like other languages  Base case  Recursive call  Author programs a number of built-in functions as examples.
Functional Programming Lecture 3 - Lists Muffy Calder.
Haskell Chapter 5, Part II. Topics  Review/More Higher Order Functions  Lambda functions  Folds.
List Operations CSCE 314 Spring CSCE 314 – Programming Studio Tuple and List Patterns Pattern matching with wildcards for tuples fst (a, _) = a.
Functional Programming Lecture 16 - Case Study: Huffman Codes con’t.
0 PROGRAMMING IN HASKELL Typeclasses and higher order functions Based on lecture notes by Graham Hutton The book “Learn You a Haskell for Great Good” (and.
© M. Winter COSC 4P41 – Functional Programming Some functions id :: a -> a id x = x const :: a -> b -> a const k _ = k ($) :: (a -> b) -> a -> b.
Advanced Functional Programming 2010
Set Comprehensions In mathematics, the comprehension notation can be used to construct new sets from old sets. {x2 | x  {1...5}} The set {1,4,9,16,25}
Set Comprehensions In mathematics, the comprehension notation can be used to construct new sets from old sets. {x2 | x  {1...5}} The set {1,4,9,16,25}
Polymorphic Functions
Functional Programming
Conditional Expressions
PROGRAMMING IN HASKELL
Types CSCE 314 Spring 2016.
ML Again ( Chapter 7) Patterns Local variable definitions
A lightening tour in 45 minutes
Haskell Chapter 4.
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
Higher-Order Functions
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
Computer Science 312 Haskell Lists 1.
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
CSCE 314: Programming Languages Dr. Dylan Shell
Haskell Types, Classes, and Functions, Currying, and Polymorphism
Higher Order Functions
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
CSCE 314: Programming Languages Dr. Dylan Shell
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
PROGRAMMING IN HASKELL
Presentation transcript:

Recursion on Lists Lecture 5, Programmeringsteknik del A.

Lifting the Bonnet Today, we take a look `under the bonnet´ and see how functions like sum, ++, and take are defined. Recursion is the key: it lets us repeat computations, to process all the list elements in turn. Even though Haskell provides a rich set of predefined functions, you will often need to define your own.

Pattern Matching on Lists The most basic way to take a list apart is via pattern matching. sum [] = 0 sum [x] = x sum [x, y] = x+y … But how can we look inside a list of arbitrary length?

A Failed Idea What about sum (xs ++ ys) = sum xs + sum ys ??? Example: [1, 2, 3] == [1] ++ [2, 3] == [1, 2] ++ [3] Can match in more than one way!

A Unique Way to Represent Lists Any (nonempty) list xs can be written as xs == [y] ++ ys in exactly one way! Examples: [1] == [1] ++ [] [1, 2] == [1] ++ ([2] ++ []) [1, 2, 3] == [1] ++ ([2] ++ ([3] ++ []))

A Unique Way to Represent Lists Any (nonempty) list xs can be written as xs == [y] ++ ys in exactly one way! Examples: [1] == [1] ++ [] [1, 2] == [1] ++ ([2] ++ []) [1, 2, 3] == [1] ++ ([2] ++ ([3] ++ [])) New notation: y : ys 1 : [] 1 : (2 : []) 1:(2:(3:[])) Pronounced ”cons”

Cons Patterns Cons (:) is allowed in patterns! x : xs Matches first element. Matches remaining elements. Examples: head :: [a] -> a head (x : xs) = x tail :: [a] -> [a] tail (x : xs) = xs

Primitive Recursion on Lists Every list matches [] or (x : xs) Base case. Recursive case. A smaller list.

Summing a List sum [1, 2] =sum (1 : (2 : [])) 1 + sum (2 : []) 1 + (2 + sum []) 1 + (2 + 0)3 sum :: [Int] -> Int sum [] = 0 sum (x : xs) = x + sum xs xy z... xs

Quiz Give a primitive recursive definition of the function length :: [a] -> Int

Quiz Give a primitive recursive definition of the function length :: [a] -> Int length [] = 0 length (x : xs) = length xs + 1

Checking for an Element elem x xsreturns True if x is an element of xs. elem 3 (1 : [2, 3, 4…])returns True if 3 == 1, or if 3 is an element of [2, 3, 4…] elem x (y : ys) = x==y || elem x ys elem x [] = False Compare: elem x xs = or [x==y | y <- xs] yz w... ys

Defining ++ How can we reduce xs++ys to a simpler problem? Compute [1,2,3] ++ (4:[5,6]) from [1,2,3] ++ [5, 6]??? Reduce ys to a smaller argument? Reduce xs to a smaller argument? Compute (1:[2,3]) ++ [4,5,6] from [2,3] ++ [4,5,6]??! = [2,3,4,5,6]

Defining ++ (++) :: [a] -> [a] -> [a] [] ++ ys = ys (x : xs) ++ ys = x : (xs ++ ys) How many function calls are required to evaluate [1..10]++[ ]? [1,2]++[3] 1 : ([2] ++ [3]) 1 : (2 : ([] ++ [3])) 1 : (2 : [3]) [1,2,3]

Quiz Define reverse :: [a] -> [a] xwzy xyzw

Quiz Define reverse :: [a] -> [a] xwzy xyzw reverse (x : xs) = reverse xs ++ [x] reverse [] = []

Sorting now is the winter of our discontent is now of our the winter It used to be said that computers spent more time sorting than anything else!

Insertion Sort sort (x : xs) = insert x (sort xs) sort [] = []

Insertion yz...uw x insert x (y : ys) | x<=y = x : y : ys | x>y = y : insert x ys insert x [] = [x]

Sorting Example sort [3,1,2] insert 3 (sort [1,2]) insert 3 (insert 1 (sort [2])) insert 3 (insert 1 (insert 2 (sort []))) insert 3 (insert 1 (insert 2 []))) insert 3 (insert 1 [2]) insert 3 [1, 2] 1 : insert 3 [2] 1 : 2 : insert 3 [] 1 : 2 : [3] [1, 2, 3]

The Type of Sort What is the type of sort? sort :: [a] -> [a] Can sort many different types of data. But not all! Consider a list of functions, for example...

The Correct Type of Sort sort :: Ord a => [a] -> [a] If a has an ordering... …then sort has this type. Sort has this type because ( a -> a -> Bool Overloaded, rather than polymorphic.

The Correct Type of elem elem x (y : ys) = x==y || elem x ys elem x [] = False The type of elem is elem :: Eq a => a -> [a] -> Bool because (==) :: Eq a => a -> a -> Bool

Polymorphism vs Overloading A polymorphic function works in the same way for every type. (e.g. length, ++). An overloaded function works in different ways for different types. (e.g. ==, <=).

Variations on List Recursion Key idea:The recursive case expresses the result in terms of the same function on a shorter list. The base case handles the shortest possible list. But the possible variations are many.

Defining init Recallinit [1, 2, 3] [1, 2] x wzyx [] zyx init :: [a] -> [a] init [x] = [] init (x : xs) = x : init xs xs Different base case. Compare this to tail (x : xs) = xs

Checking that a List is Ordered x...uzy x <= y ordered ordered :: Ord a => [a] -> Bool ordered (x : y : xs) = x <= y && ordered (y : xs) ordered [x] = True ordered [] = True More general pattern

Zip: Recursion on Two Arguments x...zy a cb zip (x : xs) (y : ys) = (x, y) : zip xs ys zip [] ys = [] zip xs [] = [] What would happen if we just defined zip [] [] = []? Both arguments get smaller. Two cases remain.

Defining take x...zy n n-1 take :: Int -> [a] -> [a] take n (x : xs) | n>0 = x : take (n-1) xs take 0 (x : xs) = [] take n [] = [] Two base cases

A Better Way of Sorting Divide the list into two roughly equal halves. Sort each half. Merge the sorted halves together.

Defining MergeSort mergeSort xs = merge (mergeSort front) (mergeSort back) wheresize = length xs `div` 2 front = take size xs back = drop size xs But when are front and back smaller than xs??

MergeSort with Base Cases mergeSort [] = [] mergeSort [x] = [x] mergeSort xs | size > 0 = merge (mergeSort front) (mergeSort back) wheresize = length xs `div` 2 front = take size xs back = drop size xs

Merging x y x <= y? merge [1, 3] [2, 4]1 : merge [3] [2, 4] 1 : 2 : merge [3] [4] 1 : 2 : 3 : merge [] [4] 1 : 2 : 3 : [4] [1,2,3,4]

Defining Merge merge :: Ord a => [a] -> [a] -> [a] merge (x : xs) (y : ys) | x <= y= x : merge xs (y : ys) | x > y= y : merge (x : xs) ys merge [] ys= ys merge xs []= xs One list gets smaller. Two possible base cases. Requires an ordering.

The Cost of Sorting Insertion Sort Sorting n elements takes n*n/2 comparisons. Merge Sort Sorting n elements takes n*log2 n comparisons. Num elements Cost by insertion Cost by merging

Recursion + Comprehensions Used together, recursion and list comprehensions can be a powerful tool. Example: Define nub :: Eq a => [a] -> [a] which removes duplicate elements from a list. E.g. nub [1,2,1,3][1,2,3]. xyxy y... remove x... y y x nub

Completing nub nub (x : xs) = x : nub [y | y<- xs, y /= x] nub [] = [] xyxy y... remove x... y y x nub

Lessons Recursion works well on lists: we reduce the problem of computing a function to the same problem for a shorter list. Often the cases we consider are f [] = …base case f (x : xs) = … f xs …recursive case Sometimes list comprehensions offer a simpler alternative to recursion: use each one where it is appropriate!

Reading This lecture covers roughly the material in Chapter The book also contains some excellent exercises, in particular at the end of section 7.5. Section 7.6 tackles a larger problem using the methods described in this lecture.