higher-order functions in ml. higher-order functions a first-order function is one whose parameters...
TRANSCRIPT
![Page 1: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/1.jpg)
Higher-order functions in ML
![Page 2: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/2.jpg)
Higher-order functions
• A first-order function is one whose parameters and result are all "data"
• A second-order function has one or more first-order functions as parameters or result
• In general, a higher-order function has one or more functions as parameters or result
• ML supports higher-order functions
![Page 3: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/3.jpg)
Doubling, revisited
• fun doubleAll [ ] = [ ]| doubleAll (h::t) = 2 * h :: (doubleAll t);– val doubleAll : int list -> int list = fn
• doubleAll [1,2,3,4,5];– val it : int list = [2, 4, 6, 8, 10]
• This is the usual heavy use of recursion
• It's time to simplify things
![Page 4: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/4.jpg)
map
• map applies a function to every element of a list and returns a list of the results
• map f [x, y, z] returns [f x, f y, f z]• Notice that map takes a function as an
argument
• Ignore for now the fact that map appears to take two arguments!
![Page 5: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/5.jpg)
Doubling list elements with map
• fun double x = 2 * x;• fun doubleAll lst = map double lst;
– val doubleAll : int list -> int list = fn
• doubleAll [1,2,3,4,5];– val it : int list = [2, 4, 6, 8, 10]
• The definition of doubleAll is simpler, but...
• ...now we need to expose double to the world
![Page 6: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/6.jpg)
Anonymous functions
• An anonymous function has the form (fn parameter => body)
• Now we can define doubleAll as fun doubleAll lst = map (fn x => x+x) lst;
• This final definition is simple and doesn't require exposing an auxiliary function
![Page 7: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/7.jpg)
The mysterious map
• ML functions all take a single argument, but...
• map double [1,2,3] works
• map (double, [1,2,3]) gives a type error• Even stranger, (map double) [1,2,3] works!
• map double;– val it : int list -> int list = fn
• map double looks like a function...how?
![Page 8: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/8.jpg)
Currying
• In ML, functions are values, and there are operations on those values
• Currying absorbs a parameter into a function, creating a new function
• map takes one argument (a function), and returns one result (also a function)
![Page 9: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/9.jpg)
Order of operations
• fun add (x, y) = x + y;– val add : (int * int) -> int = fn
• But also consider:
• fun add x y = x + y;– val add : int -> int -> int = fn
• add x y is grouped as (add x) y• and int -> int -> int as int -> (int ->
int)
![Page 10: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/10.jpg)
Writing a curried function I
• fun add x y = x + y;– val add : int -> int -> int = fn– That is, add : int -> (int -> int)– Our new add takes an int argument and produces
an (int -> int) result
• (add 5) 3; (* currying happens *)– val it : int = 8
![Page 11: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/11.jpg)
Writing a curried function II
• MLWorks> val add5 = add 5; – val add5 : int -> int = fn– Notice the use of val; we are manipulating values
• MLWorks> add5 3; (* use our new fn *)– val it : int = 8
![Page 12: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/12.jpg)
Function composition
• The function composition operator is the infix lowercase letter o
• (f o g) x gives the same result as f(g(x))• But composition gives you a way to bundle
the functions for later use; f(g(x)) requires an argument x right now
• val h = f o g; is perfectly legal ML
![Page 13: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/13.jpg)
Defining higher-order functions I
• fun apply1(f, x) = f(x);– val apply1 : (('a -> 'b) * 'a) -> 'b = fn
• apply1 (tl, [1,2,3]);– val it : int list = [2, 3]
• But:
• apply1 tl [1,2,3];– error: Function applied to argument of
wrong type
![Page 14: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/14.jpg)
Defining higher-order functions II
• fun apply2 f x = f(x);– val apply2 : ('a -> 'b) -> 'a -> 'b = fn
• apply2 tl [1,2,3];– val it : int list = [2, 3]
• apply2 (tl, [1,2,3]);– error: Function applied to argument of
wrong type
• Advantage: this form can be curried
![Page 15: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/15.jpg)
A useful function: span
• span finds elements at the front of a list that satisfy a given predicate
• Example:
• span even [2,4,6,7,8,9,10] gives [2, 4, 6]
• span isn't a built-in; we have to write it
![Page 16: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/16.jpg)
Implementing span
• fun span f L = if f(hd L) then (hd L) :: span f (tl L) else [];
• span even [2,4,6,7,8,9,10];– val it : int list = [2, 4, 6]
![Page 17: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/17.jpg)
Extending span: span2
• span returns the elements at the front of a list that satisfy a predicate
• Suppose we extend it to also return the remaining elements
• We can do it with the tools we have, but more tools would be convenient
![Page 18: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/18.jpg)
Generalized assignment
• val (a, b, c) = (8, 3, 6);– val a : int = 8
val b : int = 3val c : int = 6
• val x::xs = [1,2,3,4];– val x : int = 1
val xs : int list = [2, 3, 4]
• Generalized assignment is especially useful when a function returns a tuple
![Page 19: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/19.jpg)
Defining local values with let
• let declaration ; declaration ; . . .in expressionend
• let helps avoid redundant computations
![Page 20: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/20.jpg)
Example of let
fun circleArea (radius) = let val pi = 3.1416; fun square x = x * x in pi * square (radius) end;
![Page 21: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/21.jpg)
Implementing span2
• fun span2 f list = if f(hd list) then let val (first, second) = span2 f (tl list) in ((hd list :: first), second) end else ([], list);– val span2 : ('a -> bool) -> 'a list -> ('a list * 'a list)
= fn
• span2 even [2,4,6,7,8,9,10];– val it : (int list * int list) = ([2, 4, 6], [7, 8, 9, 10])
![Page 22: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/22.jpg)
Another built-in function: partition
• Partition breaks a list into two lists: those elements that satisfy the predicate, and those that don't
• Example:
• partition even [2,4,6,7,8,9,10];– val it : (int list * int list) = ([2, 4, 6, 8,
10], [7, 9])
![Page 23: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/23.jpg)
Quicksort
• Choose the first element as a pivot:– For [3,1,4,1,5,9,2,6,5] choose 3 as the pivot
• Break the list into elements <= pivot, andelements > pivot:– [1, 1, 2] and [4, 5, 9, 6, 5]
• Quicksort the sublists:– [1, 1, 2] and [4, 5, 5, 6, 9]
• Append the sublists with the pivot in the middle:– [1, 1, 2, 3, 4, 5, 5, 6, 9]
![Page 24: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/24.jpg)
Quicksort in ML
• fun quicksort [ ] = [ ]| quicksort (x :: xs) = let val (front, back) = partition (fn n => n <= x) xs in (quicksort front) @ (x :: (quicksort back)) end;
– val quicksort : int list -> int list = fn
• quicksort [3,1,4,1,5,9,2,6,5,3,6];– val it : int list = [1, 1, 2, 3, 3, 4, 5, 5, 6, 6, ..]
![Page 25: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/25.jpg)
foldl
• foldl op basis list repeatedly computes (element op basis), starting with the basis and using the list elements starting from the left
• foldl (op -) 10000 [1, 20, 300, 4000];– val it : int = 13719
• (4000 - (300 - (20 - (1 - 10000))));– val it : int = 13719
![Page 26: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/26.jpg)
foldr
• foldr op basis list repeatedly computes (element op basis), starting with the basis and using the list elements starting from the right
• foldr (op -) 10000 [1, 20, 300, 4000];– val it : int = 6281
• (1 - (20 - (300 - (4000 - 10000))));– val it : int = 6281
![Page 27: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/27.jpg)
Testing if a list is sorted
• The following code tests if a list is sorted:
• fun sorted [] = true| sorted [_] = true| sorted (x::y::rest) = x <= y andalso sorted (y::rest);
• This applies a (boolean) test to each adjacent pair of elements and "ANDs" the results
• Can we generalize this function?
![Page 28: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/28.jpg)
Generalizing the sorted predicate
• fun sorted [] = true| sorted [_] = true| sorted (x::y::rest) = x <= y andalso sorted (y::rest);
• The underlined part is the only part specific to this particular function
• We can replace it with a predicate passed in as a parameter
![Page 29: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/29.jpg)
pairwise
• fun pairwise f [] = true| pairwise f [_] = true| pairwise f (x::y::rest) = f(x,y) andalso pairwise f (y::rest);
• Here are the changes we have made:– Changed the name from sorted to pairwise– Added the parameter f– changed x <= y to f(x, y)
![Page 30: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/30.jpg)
Using pairwise
• pairwise (op <=) [1, 3, 5, 5, 9];– val it : bool = true
• pairwise (op <=) [1, 3, 5, 9, 5];– val it : bool = false
• pairwise (fn (x, y) => x = y - 1) [3,4,5,6,7];– val it : bool = true
• pairwise (fn (x, y) => x = y - 1) [3,4,5,7];– val it : bool = false
![Page 31: Higher-order functions in ML. Higher-order functions A first-order function is one whose parameters and result are all "data" A second-order function](https://reader035.vdocuments.mx/reader035/viewer/2022062417/5518d068550346881f8b5ce6/html5/thumbnails/31.jpg)
The End