Topic 5: Higher Order Functions 1 Recommended Exercises and Readings From Haskell: The craft of functional programming (3 rd Ed.) Exercises: 10.1, 10.2, 10.3, 10.4, 10.5, 10.6, 10.7, 10.8, 10.9, 10.10, 10.13, 10.14, 10.15, 10.16, 10.27, 10.18, 10.19, 10.20, 10.21, 10.24, 10.25, 10.26, 11.7, 11.8, 11.9, 11.10, 11.19, 11.20, 11.21 Readings: Chapter 10 Chapter 11.1, 11.2, 11.5 2
Functions We can visualize functions as a box Take some inputs Produce an output Inputs can be base types, tuples, lists, or Output can be a base type, tuple, list, or 3 Higher Order Functions In functional languages, the inputs and output can also be functions A function can take a function as a parameter A function can return a function as its result Higher order function: A function that takes one, or more, functions as a parameter and/or returns a function as its result 4
Higher Order Functions Passing a function to a function square :: Int > Int square n = n * n applytotuple :: (Int > Int) > (Int, Int, Int) > (Int, Int, Int) applytotuple f (a, b, c) = (f a, f b, f c) What s the result of applytotuple square (1, 2, 3)? 5 Higher Order Functions Write a function that computes a new list by applying a function to every element in a list First argument: The function to apply to each element Second argument: The list of elements to which the function is applied This operation is traditionally called map 6
Higher Order Functions Write a function that retains or discards items in a list First argument: A Boolean function Items that cause this function to return True will be retained Items that cause this function to return False will be discarded Second argument: The list of elements to which the function is applied This operation is traditionally called filter 7 Using Map and Filter Examples 8
Polymorphic Functions Polymorphic Function: A function that can be applied to multiple types of data Many functions in the Prelude module are polymorphic We can write our own polymorphic functions Ideally, we want one version of map that works for all data types, and one version of filter that works for all data types 9 Polymorphic Functions In Haskell: Polymorphic functions include one or more type variables in their type definition By convention, the type variables are lower case letters starting from a A function s type can include a mixture of base / list / tuple types and type variables 10
Polymorphic Functions Example: Rewrite myfilter so that it is polymorphic Do the input list and the result need to have the same type? What is the type of the function passed to mymap? 11 Polymorphic Functions Example: Rewrite mymap so that it is polymorphic Do the input list and the result need to have the same type? What is the type of the function passed to mymap? 12
Polymorphic Functions Example: Rewrite applytotuple so that it is polymorphic Do the input tuple and the result tuple need to have the same type? What is the type of the function passed to applytotuple? 13 Using Polymorphic Functions Assume the existence of the following functions: square :: Int > Int c2f :: Float > Float iseven :: Int > Bool plus :: Int > Int > Int map :: (a > b) > [a] > [b] filter :: (a > Bool) > [a] > [a] What is the result of the following expressions? map square [1.. 5] map c2f [1.0.. 5.0] map plus [1.. 5] map iseven [1.. 5] filter iseven [1.. 5] filter square [1.. 5] 14
Folding Folding reduces a list to a single value by repeatedly applying a function to the value computed so far and the next item in the list Folding can occur from the left or the right Can be viewed as inserting an operator (function) between each value in the list Examples: Left folding (+) into the list [1..5] gives ((((1 + 2) + 3) + 4) + 5) Right folding min into the list [1..5] gives (1 `min` (2 `min` (3 `min` (4 `min` 5)))) This operation is also commonly referred to as reduce 15 Folding Write a function that performs a left fold on a list of values First parameter is the function to insert between each value in the list Second parameter is the list of values to process Questions to consider: What should left fold do if the list of values is empty? What should left fold do if the list of values has length 1? What should the type of the left fold function be? 16
Folding Write a function that performs a left fold on a list of values Write a function that performs a right fold on a list of values 17 Folding in Haskell The functions that we just wrote are referred to as foldl1 and foldr1 They only work on lists that contain at least one element More general functions foldl and foldr are also available foldl :: (b > a > b) > b > [a] > b foldr :: (a > b > b) > b > [a] > b The more general function can be safely applied to an empty list The identity element is returned 18
Folding Examples Use a fold to compute the sum of all of the items in a list Use a fold to compute the minimum value in a list Use a fold to reverse the elements in a list 19 Folding Examples Use a fold to remove adjacent duplicates from a list Use a fold to decode a run length encoded list 20
Folding Examples Use a fold to sort a list 21 Other Higher Order Functions zipwith Zip combines elements from two lists, forming pairs zipwith combines elements from two lists, performing an arbitrary operation zipwith :: (a > b > c) > [a] > [b] > [c] 22
Other Higher Order Functions Use zipwith and a fold to compute the dot product of two lists dotproduct [1, 2, 3, 4] [5, 6, 7, 8] evaluates to 1*5 + 2*6 + 3*7 + 4*8 = 70 23 Other Higher Order Functions sortby (in the Data.List module) sortby :: (a > a > Ordering) > [a] > [a] Ordering is a Haskell type with three possible values: LT GT EQ 24
Other Higher Order Functions Example: Use sortby to sort a list of strings The strings should be sorted in a case insensitive manner Hint: toupper :: Char > Char is available in the Data.Char module 25 Higher Order Functions Polymorphic higher order functions Each function can be used on lists of any type Each function takes a parameter that is a function Examples: map, filter, foldr, foldl, zipwith, sortby, Make it possible to perform some complex tasks without writing very much code 26
Lambda Functions Small (even tiny) helper functions are often needed when working with higher order functions Writing named helper functions can become tedious Lambda functions provide another mechanism for writing these functions Lambda functions are anonymous they don t get a name Lambda functions are defined inline 27 Lambda Functions Lambda Notation \ is used to represent the Greek character λ \ is immediately followed by the function s parameters > separates the parameters from the function s body Example: A function that sums two numbers \x y > x + y Example: A function that converts a string to uppercase \s > [toupper ch ch < s] Example: A function that determines whether or not an integer is even 28
Lambda Functions Use higher order functions and lambda functions to write one line expressions that Remove all of the odd numbers from a list Convert a list of temperatures in Celsius to a list of temperatures in Fahrenheit Square all of the even integers in a list, discard all the odd integers 29 Functions can Return Functions The value returned by a function can be a lambda expression Example: Create a function that takes a two parameter function as its only parameter and returns a new two parameter function as its result The new function will perform the same task, but its arguments will be in the opposite order This operation is commonly referred to as flip 30
Functions can Return Functions Example: Write a function that adjusts the capitalization of a string to match speech types of whisper, normal, and loud 31 Other Languages The concepts introduced here are not unique to Haskell Some other languages allow functions to operate on many different types of values Some other languages permit a function to be passed to another function or returned as a function s result Some other languages provide map, filter and reduce operations Some other languages provide all of these features 32
Polymorphic Functions in Other Languages Python C++ 33 Higher Order Functions in Other Languages How do we pass a function as a parameter to another function in Python 34
Higher Order Functions in Other Languages How do we pass a function as a parameter to another function in C++ 35 import java.util.arrays; import java.util.list; import java.util.stream.collectors; public class Higher { public static void main(string[] args) { List<String> names = Arrays.asList("Alice", "Bob", "Chantal", "Doug"); System.out.println("Names: " + names); List<String> yelled_names = names.stream().map(string::touppercase).collect(collectors.tolist()); System.out.println("Yelled names: " + yelled_names + "\n"); List<Integer> nums = Arrays.asList(1,2,3,4,5); System.out.println("Numbers: " + nums); Map, Filter and Fold in Other Languages Java provides map, filter and reduce methods And lambda functions that can be passed to them List<Integer> squared = nums.stream().map(n > n * n).collect(collectors.tolist()); System.out.println("Squared numbers: " + squared + "\n"); } } 36
Map, Filter and Fold in Other Languages Python provides map, filter and reduce functions map and filter are part of the standard module reduce must be imported from functools 37 Map, Filter and Fold in Other Languages C++ provides map, filter and reduce functions Actually provided as std::transform, std::copy_if and std::accumulate Need to include <algorithm> for std::transform and std::copy_if Need to include <numeric> for std::accumulate Need C++11 to use lambda functions 38
Summary Higher order functions take functions as parameters Or return them as the function s result Polymorphic functions operate on many different types of data Polymorphic higher order functions are powerful tools for manipulating data, often with a small amount of code Examples: map, filter, foldl / foldr, Lambda functions reduce the need to write separate small named helper functions These constructs are not unique to Haskell 39