1 / 35

Higher-order functions in ML (Ch. 9)

Higher-order functions in ML (Ch. 9). Functionals. More pattern matching Function values and anonymous functions Higher-order functions and currying Predefined higher-order functions. Pattern-Matching in the case expression. fun f 0 = "zero" | f _ = "non-zero";. match. fun f n =

zaina
Download Presentation

Higher-order functions in ML (Ch. 9)

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Higher-order functions in ML(Ch. 9) Functionals • More pattern matching • Function values and anonymous functions • Higher-order functions and currying • Predefined higher-order functions IT 327

  2. Pattern-Matching in the case expression fun f 0 = "zero" | f _ = "non-zero"; match fun f n = case n of 0 => "zero" | _ => "non-zero"; IT 327

  3. Case Expressions <case-expr> ::= case <expression> of <match> <match> ::= <rule> <match> ::= <rule> |<match> <rule> ::= <pattern> => <expression> - case 1+1 of = 3 => "three" | = 2 => "two" | = _ => "hmm"; val it = "two" : string case x of _::_::c::_ => c | _::b::_ => b | a::_ => a | nil => 0 IT 327

  4. Generalizes if • The two expressions above are equivalent • So if-then-else is really just a special case of case if exp1 then exp2 else exp3 case exp1 of true => exp2 | false => exp3 IT 327

  5. Behind the Scenes • if := an abbreviation of case • This explains some odd SML/NJ error messages: - if 1=1 then 1 else 1.0; Error: types of if branches do not agree [literal] then branch: int else branch: real in expression: if 1 = 1 then 1 else 1.0 - if 1=1 then 1 else 1.0; Error: types of rules don't agree [literal] earlier rule(s): bool -> int this rule: bool -> real in rule: false => 1.0 New version of SML shows different message IT 327

  6. Predefined Functions • Predefined variables bound to functions: - ord;val it = fn : char -> int- ~;val it = fn : int -> int - val x = ~;val x = fn : int -> int-x 3;val it = ~3 : int IT 327

  7. Quick Sort with < < < < < < < < < < < < < < < < < < < < < < < < < < < IT 327

  8. Quick Sort with > We can make a function parameter for the meaning of ordering > > > > > > > > > > > > > > > > > > > > > > > > > > IT 327

  9. Quick Sort in ML fun split nil = (nil,nil) | split [a] = ([a],nil) | split [a,b] = if (a <= b) then ([a],[b]) else ([b],[a]) | split (a::b::c) = let val (x,y) = split (a::c) in if (a < b) then (x, b::y) else (b::x, y) end; fun quicksort nil = nil | quicksort [a] = [a] | quicksort a = let val (x,y) = split a in quicksort(x)@quicksort(y) end; This is more conceptual to the understanding of the problem IT 327

  10. Quick Sort with function parameter fun split (nil, _) = (nil,nil) | split ([a], _) = ([a],nil) | split ([a,b], f) = if f(a,b) then ([a],[b]) else ([b],[a]) | split (a::b::c, f) = let val (x,y) = split (a::c, f) in if f(a,b) then (x, b::y) else (b::x,y) end; fun quicksort (nil,_) = nil | quicksort ([a],_) = [a] | quicksort (a,f) = let val (x,y) = split (a,f) in quicksort(x,f)@quicksort(y,f) end; IT 327

  11. Anonymous Functions functions without a name -calculus IT 327

  12. Function Values • Functions in ML do not have names but can be given. • The fun syntax does two separate things: • Creates a new function value • Binds that function value to a name - fun f x = x + 2;val f=fn : int -> int- f 1;val it = 3 : int IT 327

  13. Anonymous Functions in ML • Named function: • Anonymous function: - fun f x = x + 2;val f = fn : int -> int- f 1;val it = 3 : int A match - fn x => x + 2;val it = fn : int -> int- (fn x => x + 2) 1;val it = 3 : int IT 327

  14. The fn Syntax <fun-expr> ::= fn <match> • We use fn to give an expression whose value is an (anonymous) function • The followings are the same effect: • fun f x = x + 2 • val f =fn x => x + 2 IT 327

  15. Using Anonymous Functions: - fun less (a,b) = a < b;val intBefore = fn : int * int -> bool- quicksort ([1,4,3,2,5], less);val it = [1,2,3,4,5] : int list - quicksort ([1,4,3,2,5], fn (a,b) => a<b);val it = [1,2,3,4,5] : int list- quicksort ([1,4,3,2,5], fn (a,b) => a>b);val it = [5,4,3,2,1] : int list Q: Can we do the same in Java or C++? IT 327

  16. The op keyword - *; Error: expression or pattern begins with infix identifier "*" • Binary operators are special functions • op gives the underlying function - op *; val it = fn : int * int -> int - op <; val it = fn : int * int -> bool - quicksort ([1,4,3,2,5], op<); val it = [1,2,3,4,5] : int list IT 327

  17. Higher-order Functions • Every function has an order: • A function that does not take any functions as parameters, and does not return a function value, has order 1 • A function that takes a function as a parameter or returns a function value has order n+1, where n is the order of its highest-order parameter or returned value • The quicksort we just saw is a second-order function A little digression with more precise notions on higher-ordered Functionals (CiE 2006) IT 327

  18. Examples: -> is right-associative 1st order int * int -> bool int list * (int * int -> bool) -> int list int -> int -> int (int -> int) * (int -> int) -> (int -> int) int -> bool -> real -> string ('a -> 'b) * ('c -> 'a) -> 'c -> 'b int -> int -> int -> int -> int -> int 2nd order 2nd order 2nd order 3rd order 2nd order 5th order IT 327

  19. Haskell B. Curry (1900-1982) Curry-Howard logic Currying • a 2-tuple looks like two parameters:fun f (a,b) = a + b; • Another way: fun g a = fn b => a+b; • The general name for this is currying f (2,3); g 2 3; (fn b => 2+b) 3 5 IT 327

  20. Curried Addition -> is right-associative - fun f (a,b) = a+b; val f = fn : int * int -> int - fun g a = fn b => a+b; val g = fn : int -> int -> int - f(2,3); val it = 5 : int - g 2 3; val it = 5 : int • function application is left-associative • So g 2 3 means ((g 2) 3) IT 327

  21. Advantages • No tuples: we get to write g 2 3 instead of f(2,3) • The real advantage: we can specialize functions for particular initial parameters - fun g a = fn b => a+b; • val add2 = g 2;val add2 = fn : int -> int - add2 3;val it = 5 : int- add2 10;val it = 12 : int S-m-n Theorem IT 327

  22. Example: • quicksort (op <) [1,4,3,2,5];val it = [1,2,3,4,5] : int list • val sortBackward = quicksort (op >);val sortBackward = fn : int list -> int list - sortBackward [1,4,3,2,5];val it = [5,4,3,2,1] : int list • val sortForward = quicksort (op <);val sortBackward = fn : int list -> int list - sortForward [1,4,3,2,5];val it = [1,2,3,4,5] : int list • Let quicksort be written in the Currying form, in which the comparison function is a first, curried parameter. IT 327

  23. Multiple Curried Parameters • fun f (a,b,c) = a+b+c;val f = fn : int * int * int -> int - fun g a = fn b => fn c => a+b+c; val g = fn : int -> int -> int -> int • f (1,2,3);val it = 6 : int • g 1 2 3;val it = 6 : int IT 327

  24. Notation For Currying • Explicit intermediate anonymous functions • There is a simpler notation much easier to read and write fun g a = fn b => fn c => a+b+c; IT 327

  25. Easier Notation for Currying fun f a = fn b => a+b; same as: fun f a b = a+b; fun g a = fn b => fn c => a+b+c; Same as: fun g a b c = a+b+c; • fun f a b c d = a+b+c+d; val f = fn : int -> int -> int -> int -> int IT 327

  26. Predefined Higher-Order Functions • map (map a function to a list) • foldr (fold an operation from the right) • foldl (fold an operation from the left) IT 327

  27. The map Function • Apply a function to every element of a list, and collect a list of results - map ~ [1,2,3,4];val it = [~1,~2,~3,~4] : int list - map (fn x => x+1) [1,2,3,4];val it = [2,3,4,5] : int list - map (fn x => x mod 2 = 0) [1,2,3,4];val it = [false,true,false,true] : bool list - map (op +) [(1,2),(3,4),(5,6)];val it = [3,7,11] : int list IT 327

  28. The map Function Is Curried - map; val it = fn : ('a -> 'b) -> 'a list -> 'b list - map (fn x => x+1)[1,2,3,4];val it = [2,3,4,5] : int list • val f = map (op +);val f = fn : (int * int) list -> int list - f [(1,2),(3,4)];val it = [3,7] : int list IT 327

  29. Define your own map fun mymap _ nil = nil | mymap f (a::t) = f a:: mymap f t; IT 327

  30. The foldr Function Perform the binary operation on all the elements of a list from the right(tail) foldr f c x where x = [x1, …, xn] and computes: foldr (op +) 0 [1,2,3,4] evaluates as 1+(2+(3+(4+0)))=10 IT 327

  31. Examples • foldr (op +) 0 [1,2,3,4];val it = 10 : int • foldr (op * ) 1 [1,2,3,4];val it = 24 : int • foldr (op ^) "" ["abc","def","ghi"];val it = "abcdefghi" : string - foldr (op ::) [5] [1,2,3,4];val it = [1,2,3,4,5] : int list 4::[5] IT 327

  32. The foldr Function Is Curried - foldr; val it = fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b - foldr (op +); val it = fn : int -> int list -> int - foldr (op +) 0; val it = fn : int list -> int - val sum = foldr (op +) 0; val sum = fn : int list -> int - sum [1,2,3,4,5]; val it = 15 : int IT 327

  33. The foldl Function Perform the binary operation on all the elements of a list from theleft(head) foldl f c x where x = [x1, …, xn] and computes: So foldl (op +) 0 [1,2,3,4]  4+(3+(2+(1+0)))=10 foldr (op +) 0 [1,2,3,4] 1+(2+(3+(4+0)))=10 IT 327

  34. Commutative • ^ is not commutative • foldl and foldr are the same if the function is associative and commutative, like + and * • foldr (op ^) "" ["abc","def","ghi"];val it = "abcdefghi" : string • foldl (op ^) "" ["abc","def","ghi"];val it = "ghidefabc" : string • foldr (op -) 0 [1,2,3,4];val it = ~2 : int - foldl (op -) 0 [1,2,3,4];val it = 2 : int • – is neither associative nor commutative IT 327

  35. Homework 4 Chapter 9.  Exercises:  3, 6, 10, 26, 27, 28 plus 4 questions to be announced. IT 327

More Related