(*
* 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 *)
               (
geocities.com/htrefftz/mum/cs505)                   (
geocities.com/htrefftz/mum)                   (
geocities.com/htrefftz)