(* * More on HOF *) (* diadic plus, curried *) fun plus x y = x + y; (* partial application *) val plus1 = plus 1; (* use it *) plus1 100; (* plus, uncurried *) fun uplus (x,y):int = x + y; (* to curry a function *) (* f takes its arguments as a tuple *) fun curry f x y = f(x,y); val $ = curry; (* use curry, note left-associativity *) curry uplus 3 4; (* UNcurry a function *) (* f takes curried arguments *) fun uncurry f(x,y) = f x y; val ~$ = uncurry; (* use uncurry, note left associativity *) uncurry plus (3,4); (* use it *) val plus2 = curry uplus 2; plus2 100; (* use SML's + sign *) val plus3 = curry op+ 3; plus3 100; (* compose functions *) fun double x:int = 2 * x; fun square x:int = x * x; (* compose them *) (double o square) 2; (square o double) 2; val dobsqu = double o square; val squdob = square o double; dobsqu 2; squdob 2; (* create a list of integers from 0 to k*) fun from (k:int) :int list = let fun upto (lo:int) (hi:int) = if lo > hi then [] else lo :: upto (lo+1) hi in upto 0 k end; (* use it *) from 10; (* using patterns *) fun linst 0 = [0] | linst i = i :: linst (i-1); (* use it *) linst 10; (* numeric methods revisited *) (* specific criteria for the convergence test *) fun etest (erv:real) (x:real, xn:real):bool = abs(x - xn) / x < erv; val done:real*real -> bool = etest 1.0e~4; (* abstract-out the details from the old Newton-Raphson method*) fun iterates (done:real * real -> bool) (f:real -> real) (x:real) : real = let val next = f x in if done (x, next) then next else iterates done f next end; (* define nextx, how to find x for the next iteration *) fun nextx (a:real) (x:real) = (a/x + x)/2.0; (* now bild the square root function *) fun sqrtf a = iterates done (nextx a) 1.0; (* use it *) sqrtf 9.0; (* numerical integration *) fun integrate (f:real->real) (lo:real) (hi:real) (dx:real) = let val now = dx * f lo in if lo > hi then 0.0 else now + integrate f (lo+dx) hi dx end; val Pi = 3.141592765; (* sin is not defined integrate sin 0.0 Pi 0.1; *) fun invert x = 1.0/x; val e = 2.71828; integrate invert 1.0 e 0.01; (* result: 1.0 *) fun square x:real = x * x; (* compose invert and square functions *) (* resulting function is 1/x*x *) integrate (invert o square) 1.0 10.0 0.01; (* Higher order functions for lists *) (* map: apply function f to each element in the list *) fun map (f:'a->'b) (nil:'a list) :('b list) = [] | map f (x::xs) = (f x) :: map f xs; (* filter: return a list where the elements pass test f *) fun filter (f:'a->bool) (nil:'a list) :('a list)= [] | filter f (x::xs) = if f x then x :: filter f xs else filter f xs; (* reduce: combine all the elments in the list *) (* u is the identity element for operation f *) fun reduce (f:'a->'b->'b) (u:'b) (nil:'a list) :'b = u | reduce f u (x::xs) = f x (reduce f u xs); (* create a list of integers from lo to hi*) fun fromTo lo hi = if lo > hi then [] else lo :: fromTo (lo+1) hi; (* create a list of integers from 0 to ...*) val upto = fromTo 0; val data = upto 8; (* map *) map (square o real) (data); (* [1., 4., 9., ...] *) (* filter *) filter ($ op< 4) (data); (* [5., 6., 7., ...] *) (* reduce *) (* note that sumlist waits to consume a list *) val (sumlist:int list -> int) = reduce ($ op+) 0; sumlist data; val One = fn x:'a => 1; (* length returns the list of a list of any type *) fun length (x:'a list) = sumlist (map One x); length data; (* 9 *)