(* Dan Grossman, CSE341 Spring 2008, Lecture 9 *)
(* An ADT using higher-order functions *)
(* a set with two operations ("methods") *)
datatype set = S of { add : int -> set, member : int -> bool }
(* a set constructor *)
val empty_set =
let fun exists(j,lst) = (* could use currying and/or fold to be fancier *)
case lst of
[] => false
| hd::tl => j=hd orelse exists(j,tl)
fun make_set lst = (* lst is a "private field" *)
S { add = fn i => make_set (i::lst),
member = fn i => exists (i,lst) }
in
make_set []
end
(* example client *)
fun use_a_set () =
let val S s1 = empty_set
val S s2 = (#add s1) 34
val S s3 = (#add s2) 19
in
if (#member s3) 42
then 99
else if (#member s3) 19
then 17
else 0
end
(* currying examples
(including reimplementing some List-library functions) *)
val inorder3 = fn x => fn y => fn z =>
z >= y andalso y >= x
val true1 = ((inorder3 4) 5) 6
val true2 = inorder3 4 5 6
val inorder3_tupled = fn (x,y,z) => z >= y andalso y >= x
val true3 = inorder3_tupled(4,5,6)
fun is_nonnegative1 x = inorder3 0 0 x
val is_nonnegative2 = inorder3 0 0
fun fold f = fn acc => fn l =>
case l of
[] => acc
| hd::tl => fold f (f(acc,hd)) tl
fun sum1 l = fold (fn (x,y) => x+y) 0 l
val sum2 = fold (fn (x,y) => x+y) 0
fun fold_with_sugar f acc l =
case l of
[] => acc
| hd::tl => fold_with_sugar f (f(acc,hd)) tl
fun exists predicate lst =
case lst of
[] => false
| hd::tl => predicate hd orelse exists predicate tl
fun other_curry1 f = fn x => fn y => f y x
fun other_curry2 f x y = f y x
fun curry f x y = f (x,y)
fun uncurry f (x,y) = f x y
(* code describing our callback example *)
val cbs : (int -> unit) list ref = ref []
fun onKeyEvent f = cbs := f::(!cbs)
fun on_event i =
let fun loop l =
case l of
[] => ()
| f::tl => (f i; loop tl)
in loop (!cbs) end