(* Meeting 12: SML: Induction *) exception Unimplemented; (*******************************************************************) (* REVIEW *) (* Higher-Order Functions and Currying *) (* EXERCISE: Write a function constantly : 'a -> ('b -> 'a) that when applied to a value k returns a function that yields k whenever it is applied *) val constantly = fn k => (fn a => k) (* also write the type 'a -> 'b -> 'a. -> is right associative. *) fun constantly k = (fn a => k) fun constantly k a = k; (* Observe the white space between k and a *) constantly 42; (* Creates a new function bundled with its environment (i.e., a closure) (not declared anywhere else). Observe that this is a new instance of the code (fn a => k). This makes ML higher-order functions more powerful than C's function pointers. *) (* Slightly more interesting. A function plusbyn : int -> (int -> int) that creates an "incrementer by n" function. *) fun plusbyn n = (fn x => x + n) val plusby2 = plusbyn 2; plusby2 7; plusby2 21; fun plusbyn n x = x + n val plusby3 = plusbyn 3; plusby3 7; plusbyn 3 4; (* plusbyn looks just like plus, a function that takes two ints and adds them *) fun plus (x,y) = x + y (* The process of converting plus to plusbyn is called currying. *) fun curry f x y = f (x, y) (* EXERCISE: What's the type of curry? *) (* x : 'a, y : 'b, f : 'c f : 'a * 'b -> 'd (= 'c) curry : ('a * 'b -> 'd) -> 'a -> 'b -> 'd *) (* It's not different with functions on datatypes. *) (* map f l *) fun map f nil = nil | map f (h :: t) = (f h) :: (map f t) (* EXERCISE: What's the type of this map? *) (* f : 'a, l : 'b list return : 'c list f : 'd -> 'e (= 'a) f : 'b -> 'e ('d = 'b) f : 'b -> 'c ('c = 'e) map : ('b -> 'c) -> 'b list -> 'c list map : ('b -> 'c) -> ('b list -> 'c list) *) fun map (f, nil) = nil | map (f, (h :: t)) = (f h) :: (map (f,t)) (* map : (('b -> 'c) * 'b list) -> 'c list *) (* Currying allows us to stage computation. *) (* Fibonacci, the slow way. *) fun slowfib 0 = 1 | slowfib 1 = 1 | slowfib n = slowfib (n - 1) + slowfib (n - 2) (* Add to the nth fibonacci number *) fun fibplus (n: int, x: int) = let val fib = slowfib n in fib + x end; fibplus (40, 2); fibplus (40, 5); fibplus (40, 7); (* Curry fibplus. *) fun fibplus_curried (n: int) (x: int) = let val fib = slowfib n in fib + x end val fibnplus = fibplus_curried 40; fibnplus 2; fibnplus 5; fibnplus 7; (* Curry fibplus, but stage the computation *) fun fibplus_staged (n: int) = let val fib = slowfib n (* as soon as we have n, find the nth fib number *) in fn x => fib + x (* return function that adds x *) end val fibnplus_staged = fibplus_staged 40; (* slowfib 40 computed here *) fibnplus_staged 2; fibnplus_staged 5; fibnplus_staged 7; val myfunc = (fn x => (fn y => x + y)) (* int -> (int -> int) *) fun myfunc x y = x * y val x = 1 val x = 2