(* Some sample solutions to Louden Exercise 11.8 *) (* a *) fun tail_recursive_length (xs: 'a list) : int = let fun accumulating_length (xs : 'a list) (length_so_far : int) = case xs of [] => length_so_far | _::xs' => accumulating_length xs' (length_so_far+1) in accumulating_length xs 0 end (* b *) exception Empty fun maxmin (xs : int list) : int * int = case xs of [] => raise Empty | [x] => (x,x) | x::xs' => let val (max_xs',min_xs') = maxmin xs' in (Int.max (x,max_xs'),Int.min (x,min_xs')) end (* c *) exception BadInput fun read_until_zero () : int list = case TextIO.scanStream (Int.scan StringCvt.DEC) TextIO.stdIn of SOME 0 => [] | SOME i => i::(read_until_zero()) | NONE => raise BadInput (* d *) fun doit () : unit = let val _ = print "enter your numbers:\n" val xs = read_until_zero () val _ = print "you entered:\n" val _ = app (fn x => print(Int.toString x ^ "\n")) xs val (mx,mn) = maxmin xs in print ("max = " ^ (Int.toString mx) ^ "\n"); print ("min = " ^ (Int.toString mn) ^ "\n") end (* e *) fun quicksort (xs:int list) : int list = let fun partition (p:'a -> bool) (xs:'a list) : ('a list * 'a list) = (* actually, this is already in the list library *) case xs of [] => ([],[]) | (x::xs') => let val (t,f) = partition p xs' in if p x then (x::t,f) else (t,x::f) end in case xs of [] => [] | (x::xs') => (* for simplicity, just use first element as pivot *) let val (left,right) = partition (fn x' => x' < x) xs' in (quicksort left) @ (x::quicksort right) end end (* f *) fun mergesort (xs:int list) : int list = let fun split (xs : 'a list) : ('a list * 'a list) = (* a simple way to divide the list in two without knowing its length *) case xs of [] => ([],[]) | [x] => ([x],[]) | (x1::x2::xs') => let val (xs1', xs2') = split xs' in (x1::xs1',x2::xs2') end fun merge (ys: int list) (zs: int list) : int list = case (ys,zs) of ([],_) => zs | (_,[]) => ys | (y::ys',z::zs') => if y < z then y::(merge ys' zs) else z::(merge ys zs') in case xs of [] => [] | [x] => [x] | _ => let val (ys,zs) = split xs in merge (mergesort ys) (mergesort zs) end end (* g *) fun pythagorean_triples (n: int) : unit = let fun loop_to_n (i:int) (f: int -> unit) : unit = if i > n then () else (f i; loop_to_n (i+1) f) in loop_to_n 1 (fn x => loop_to_n (x+1) (fn y => loop_to_n (y+1) (fn z => if x*x + y*y = z*z then print ((Int.toString x) ^ " " ^ (Int.toString y) ^ " " ^ (Int.toString z) ^ "\n") else ()))) end (* h *) fun twice f x = f (f x) (* i *) fun inc_n n x = x + n