Recursion Higher Order Functions CSCE 314 Spring 2016 CSCE 314 – Programming Studio More on Recursion: Multiple Arguments • Functions can be defined with multiple arguments • We’ve seen this already insert :: Ord a => a -> [a] -> [a] insert x [] = [x] insert x (y:ys) | x <= y = x:y:ys | otherwise = y:insert x ys Spring 2016 CSCE 314 – Programming Studio More on Recursion: Multiple Recursion • Functions can recursively call themselves multiple times • Again, we’ve seen this before quicksort :: [a] -> [a] quicksort[] = [] quicksort (x:xs) = quicksort (smallerlist x xs) ++ [x] ++ quicksort (biggerlist x xs) Spring 2016 CSCE 314 – Programming Studio More on Recursion: Mutual recursion • Two separate functions can each call each other even 0 = True even n = odd n-1 odd 0 = False odd (n+1) = even n -- Note: this (n+1) is an integer pattern -- We can only use addition in an integer pattern Spring 2016 CSCE 314 – Programming Studio Recursion Overview 1. 2. 3. 4. 5. Define the type Enumerate the cases Define the simple (base) cases Define the other cases Generalize and simplify Spring 2016 CSCE 314 – Programming Studio Example: product (product of list of ints) 1. Define the type product :: [Int] -> [Int] 2. Enumerate the cases product [] product (x:xs) 3. Define the simple (base) cases product [] = 1 4. Define the other cases product (x:xs) = x * (product xs) 5. Generalize and simplify … -- can simplify with functions to be seen Spring 2016 CSCE 314 – Programming Studio Higher-order functions • We’ve seen (via currying) that a function can produce a function as output • Functions can also take a function as input • The map function is an example we’ve seen map :: (a -> b) -> [a] -> [b] • Can define map using a list comprehension map f xs = [f x | x <- xs] • Can define map using recursion map f [] = [] map f (x:xs) = f x : map f xs Spring 2016 CSCE 314 – Programming Studio The Filter function • Another higher-order function • Takes in a function and a list, produces a list • Function returns Bool, filter returns a list of those items that meet function filter :: (a -> Bool) -> [a] -> [Bool] • Can be defined using a list comprehension filter p xs = [x <- xs, p x] • Alternatively can be defined using a recursion filter filter | | p [] = [] p (x:xs) p x = x : filter p xs otherwise = filter p xs Spring 2016 CSCE 314 – Programming Studio Some other higher-order functions • all • True if and only if all elements of list meet some function • any • True if and only if some element of a list meets some function • takeWhile • Takes elements of a list while they meet some function • dropWhile • Drops elements of a list while they meet some function Spring 2016 CSCE 314 – Programming Studio Can you see a pattern? sum [] = 0 sum (x:xs) = x + (sum xs) v = 0 op = + product [] = 1 product (x:xs) = x * (product xs) v = 1 op = * and [] = True and (x:xs) = x && (and xs) v = True op = && f [] = v f (x:xs) = x op f xs Spring 2016 CSCE 314 – Programming Studio The foldr function • Captures this behavior foldr :: (a -> b -> b) -> b -> [a] -> b foldr op v [] = v foldr op v (x:xs) = op x (foldr op v xs) • So, the earlier examples: product ls = foldr (*) 1 ls sum ls = foldr (+) 0 ls length ls = foldr (\_ n -> 1 + n) 0 ls Spring 2016 CSCE 314 – Programming Studio Another way of thinking of foldr • Each : in the list is replaced by the binary op • [] is replaced by the given value v • Example: sum [1, 2, 3] = foldr (+) 0 [1, 2, 3] = foldr (+) 0 (1:(2:(3:[]))) = 1+(2(+(3+0))) = 6 Spring 2016 CSCE 314 – Programming Studio Other foldr examples • The foldr function can actually represent a very wide set of functions • Example: length length :: [a] -> Int length [] = 0 length (_:xs) = 1 + length xs Spring 2016 CSCE 314 – Programming Studio foldr example for length Example: length [1, 2, 3] = length (1:(2:(3:[]))) = 1+(1+(1+0))) = 3 What is v? 0 What is op? \_ n -> 1+n So, length = foldr (\_ n -> 1+n) 0 Spring 2016 CSCE 314 – Programming Studio Why use foldr? • Some recursive functions are simpler to define with foldr • Properties of functions defined using foldr can be proved using algebraic properties of foldr • Advanced program optimizations are simpler if foldr is used in place of explicit recursion Spring 2016 CSCE 314 – Programming Studio Next time • More on higher-order functions • foldl, composition • Data types Spring 2016