About CTM The following Alice ML code is derived from the examples provided in the book:
      "Concepts, Techniques, and Models of Computer Programming" by Peter Van Roy and Seif Haridi.
      http://www2.info.ucl.ac.be/people/PVR/book.html

(* CTM Chapter #03 Examples in Alice ML *)
import structure Url        from "x-alice:/lib/system/Url"
import structure HttpClient from "x-alice:/lib/system/HttpClient"
import structure Gtk        from "x-alice:/lib/gtk/Gtk"

(* syntactic sugar for solutions using promises/futures *)
open Promise
open Future
infix 3 ?=
val op?= = fulfill
val ? = future

(* 3.1.3 Implementing components in the declarative model *)
val x = 1
val y = 2
val z = promise();
if (x > y) then z ?= x else z ?=y;

(* 3.2.1 Iterative computation - A general schema *)
fun abs' x =
   if (x < 0.0)
      then ~x
      else x
fun goodEnough guess x =
   (abs'(x - guess*guess) / x) < 0.00001
fun improve guess x =
   (guess + x/guess) / 2.0
fun sqrtIter guess x =
   if (goodEnough guess x)
      then guess
      else sqrtIter (improve guess x) x
fun sqrt x =
   let
      val guess = 1.0
   in
      sqrtIter guess x
   end;

(* 3.2.3 Iterative computation - Using local procedures *)
local
   fun goodEnough guess x =
      (abs'(x - guess*guess) / x) < 0.00001
   fun improve guess x =
      (guess + x/guess) / 2.0
   fun sqrtIter guess x =
      if (goodEnough guess x)
         then guess
         else sqrtIter (improve guess x) x
in
   fun sqrt x =
      let
         val guess = 1.0
      in
         sqrtIter guess x
      end;
   end;

fun sqrt x =
   let
      fun goodEnough guess x =
         (abs'(x - guess*guess) / x) < 0.00001
      fun sqrtIter guess x =
         let
            fun improve guess x =
               (guess + x/guess) / 2.0
         in
            if (goodEnough guess x)
               then guess
               else sqrtIter (improve guess x) x
         end
      val guess = 1.0
   in
     sqrtIter guess x
   end;

fun sqrt x =
   let
      fun sqrtIter guess =
         let
            fun improve() =
               (guess + x/guess) / 2.0
            fun goodEnough() =
               (abs'(x - guess*guess) / x) < 0.00001
         in
            if goodEnough()
               then guess
               else sqrtIter (improve())
         end
      val guess = 1.0
   in
     sqrtIter guess
   end;

(* 3.2.4 Iterative computation - From general schema to control abstraction *)
fun sqrt x =
   let
      fun improve guess =
         (guess + x/guess) / 2.0
      fun goodEnough guess =
         (abs'(x - guess*guess) / x) < 0.00001
      fun sqrtIter guess =
         if (goodEnough guess)
            then guess
            else sqrtIter (improve guess)
      val guess = 1.0
   in
     sqrtIter guess
   end;

fun iterate transform isdone s =
   if (isdone s)
      then s
      else iterate transform isdone (transform(s))

fun sqrt x =
   iterate
      (fn guess => (guess + x/guess) / 2.0)
      (fn guess => (abs'(x - guess*guess) / x) < 0.00001)
      1.0;

(* 3.3 Recursive computation *)
fun fact n =
   if (n = 0)
      then 1
      else
         if (n > 0)
            then n * fact (n-1)
            else raise Domain;
inspect (fact 5);

(* 3.3.1 Recursive computation - Growing stack size *)
fun fact n r =
   if (n = 0)
      then r ?= 1
      else
         if (n > 0)
            then
               let
                  val n1 = n - 1
                  val r1 = promise()
               in
                  fact n1 r1;
                  r ?= n * ?r1
               end
            else raise Domain;
val r = promise();
fact 5 r;

(* 3.3.3 Converting a recursive to an iterative computation *)
fun fact n =
   let
      fun factIter n a =
         if (n = 0)
            then a
            else
               if (n > 0)
                  then factIter (n-1) (a*n)
                  else raise Domain
   in
      factIter n 1
   end;

(* 3.4.2.1 Programming with lists - Thinking recursively *)
fun length' []       = 0
  | length' (x::xs)  = 1 + length' xs;
inspect (length' ["a", "b", "c"]);

fun append' [] ys      = ys
  | append' (x::xs) ys = x :: (append' xs ys);
inspect (append' [1, 2, 3] [4, 5, 6]);

(* 3.4.2.2 Programming with lists - Recursive functions and their domains *)
fun nth' xs n if (n = 1) = hd xs
  | nth' xs n if (n > 1) = nth' (tl xs) (n - 1)
  | nth' xs n = raise Domain;
inspect (nth' ["a", "b", "c", "d"] 5) handle Empty => ();
inspect (nth' [1, 2, 3] 2);

fun sumList []      = 0
  | sumList (x::xs) = x + sumList(xs);
inspect (sumList [1, 2, 3]);

(* 3.4.2.3 Programming with lists - Naive implementations are often slow *)
fun reverse []      = []
  | reverse (x::xs) = append' (reverse xs) [x];

(* 3.4.2.4 Programming with lists - Converting recursive to iterative computations *)
fun length' []       = 0
  | length' (x::xs)  = 1 + length' xs;

fun iterLength i []      = i
  | iterLength i (_::xs) = iterLength (i + 1) (xs);

local
   fun iterLength i []      = i
     | iterLength i (_::xs) = iterLength (i + 1) (xs)
in
   fun length' xs =
      iterLength 0 xs
end;

local
   fun iterReverse rs [] = rs
     | iterReverse rs (y::yr) = iterReverse (y::rs) yr
in
   fun reverse xs =
      iterReverse [] xs
end;

(* 3.4.2.6 Programming with lists - Constructing programs by following the type *)
datatype 'a nestedlist = Leaf of 'a
                       | Branch of 'a nestedlist list

fun lengthL (Branch [])      = 0
  | lengthL (Branch (x::xs)) = lengthL(x) + lengthL(Branch xs)
  | lengthL (Leaf x)         = 1

fun lengthL2 (Branch [])      = 1
  | lengthL2 (Branch (x::xs)) = lengthL2(x) + lengthL2(Branch xs)
  | lengthL2 (Leaf x)         = 1

val x = Branch [
           Branch [Leaf 1, Leaf 2],
           Leaf 4,
           Branch [],
           Branch [Branch [Leaf 5], Leaf 10]
        ];
inspect (lengthL x);
inspect (lengthL2 x);

(* additional info *)
   (* lengthL is the same as counting the number of leaves *)
   fun leaves (Leaf _)      = 1
     | leaves (Branch kids) = foldl op+ 0 (map leaves kids)

   val x = Branch [
               Branch [Leaf "hello"],
               Leaf "lovely",
               Branch [Leaf "world", Leaf "!"]];
   inspect (leaves x);
(* end additional info *)

(* 3.4.2.7 Programming with lists - Sorting with mergesort *)

(* note: probably need to convert these to iterative form *)
fun merge (nil, ys) = ys
  | merge (xs, nil) = xs
  | merge (x::xs, y::ys) =
      if (x < y)
         then x::merge(xs, y::ys)
         else y::merge(x::xs, ys)

fun split nil = (nil, nil)
  | split (x::nil) = ([x], nil)
  | split (x::y::xs) =
      let
         val (ys, zs) = split xs
      in
         (x::ys, y::zs)
      end

fun mergesort nil = nil
  | mergesort (x::nil) = [x]
  | mergesort xs =
      let
         val (ys, zs) = split xs
      in
         merge(mergesort ys, mergesort zs)
      end;

inspect (mergesort [3,2,4,1]);

(* 3.4.3 Programming with lists - Accumulators *)
datatype 'a expression = Item of 'a
                       | Plus of 'a expression * 'a expression;
datatype 'a compiled = CLeaf
                     | CPlus of 'a compiled
                     | CPush of 'a * 'a compiled

fun exprcode(Plus(a, b), c1, cn, s1, sn) =
   let
      val c2 = CPlus c1
      val s2 = s1 + 1
      val c3 = promise()
      val s3 = promise()
   in
      exprcode(b, c2, c3, s2, s3);
      exprcode(a, future c3, cn, future s3, sn)
   end
  | exprcode(Item i, c1, cn, s1, sn) =
   let
   in
      cn ?= CPush(i, c1);
      sn ?= s1 + 1
   end

val code = promise()
val siz = promise()
val _ = exprcode(Plus(Plus(Item "a", Item "3"), Item "b"), CLeaf, code, 0, siz);
inspect (future code);
inspect (future siz);

fun merge (nil, ys) = ys
  | merge (xs, nil) = xs
  | merge (x::xs, y::ys) =
      if (x < y)
         then x::merge(xs, y::ys)
         else y::merge(x::xs, ys)

fun mergesort xs =
   let
      fun mergesortacc(xs, 0)    = (nil, xs)
        | mergesortacc(x::xs, 1) = ([x], xs)
        | mergesortacc(xs, n) =
            let
               val nl = n div 2
               val nr = n - nl
               val (ys, x2) = mergesortacc(xs, nl)
               val (zs, x3) = mergesortacc(x2, nr)
            in
               (merge(ys, zs), x3)
            end
      val (sorted, _) = mergesortacc(xs, length xs)
   in
      sorted
   end;

inspect (mergesort [3,2,4,1]);

(* 3.4.4 Programming with lists - Difference lists *)
fun appendD(d1, d2) =
   let
      val (s1, p1) = d1
      val (s2, p2) = d2
   in
      fulfill(p1, s2);
      (s1, p2)
   end;

val px = promise()
val py = promise();
inspect (appendD((1::2::3::future(px), px), (4::5::future(py), py)));

fun append' (nil, ys)   = ys
  | append' (x::xs, ys) = x::append'(xs, ys);

datatype 'a nestedlist = Leaf of 'a
                       | Branch of 'a nestedlist list

fun flatten (Leaf x)         = [x]
  | flatten (Branch nil)     = nil
  | flatten (Branch (x::xs)) = append'(flatten x, flatten (Branch xs))

val x = Branch [
           Branch [Leaf #"a", Leaf #"b"],
           Branch [Branch [Leaf #"c"], Branch [Leaf #"d"]],
           Branch [],
           Branch [Leaf #"e", Branch [Leaf #"f"]]];
inspect (flatten x);

fun flatten xs =
   let
      fun flattenD (Branch nil, e) = e
        | flattenD (Branch ((Branch x)::xr), e) = flattenD(Branch x, flattenD(Branch xr, e))
        | flattenD (Branch ((Leaf   x)::xr), e) = x::flattenD(Branch xr, e)
        | flattenD (Leaf x, e) = x::e
   in
      flattenD(xs, [])
   end

fun flatten xs =
   let
      fun flattenD (Branch nil, ds) =
            let
               val (s, e) = ds
            in
               fulfill(s, e)
            end
        | flattenD (Branch ((Branch x)::xr), ds) =
            let
               val (s, e) = ds
               val y2 = promise()
            in
               flattenD(Branch x, (s, future(y2)));
               flattenD(Branch xr, (y2, e))
            end
        | flattenD (Branch ((Leaf x)::xr), ds) =
            let
               val (s, e) = ds
               val y1 = promise()
            in
               fulfill(s, x::(future y1));
               flattenD(Branch xr, (y1, e))
            end
        | flattenD (Leaf x, ds) =
            let
               val (s, e) = ds
            in
               fulfill(s, x::e)
            end
      val s = promise()
   in
      flattenD(xs, (s, []));
      future(s)
   end

fun flatten xs =
   let
      fun flattenD (Branch nil, s, e) = fulfill(s, e)
        | flattenD (Branch ((Branch x)::xr), s, e) =
            let
               val y2 = promise()
            in
               flattenD(Branch x, s, future(y2));
               flattenD(Branch xr, y2, e)
            end
        | flattenD (Branch ((Leaf x)::xr), s, e) =
            let
               val y1 = promise()
            in
               fulfill(s, x::(future y1));
               flattenD(Branch xr, y1, e)
            end
        | flattenD (Leaf x, s, e) = fulfill(s, x::e)
      val s = promise()
   in
      flattenD(xs, s, []);
      future(s)
   end

fun flatten xs =
   let
      fun flattenD (Branch nil, e) = e
        | flattenD (Branch ((Branch x)::xr), e) = flattenD(Branch x, flattenD(Branch xr, e))
        | flattenD (Branch ((Leaf   x)::xr), e) = x::flattenD(Branch xr, e)
        | flattenD (Leaf x, e) = x::e
   in
      flattenD(xs, [])
   end

fun reverse' xs =
   let
      fun reverseD (Branch nil, y1, y) = fulfill(y1, y)
        | reverseD (Branch (x::xr), y1, Branch y) =
            reverseD(Branch xr, y1, Branch (x::y))
        | reverseD (Leaf x, y1, y) = fulfill(y1, Leaf x)
      val y1 = promise()
   in
      reverseD(xs, y1, Branch nil);
      future(y1)
   end

(* 3.4.5 Queues *)

(* naive queue *)
fun butLast ([y], x, l1) =
      let
         val _ = fulfill(x, y)
         val _ = fulfill(l1, [])
      in
         (future x, future l1)
      end
  | butLast (y::l2, x, l1) =
      let
         val l3 = promise()
         val _ = fulfill(l1, y::(future l3))
      in
         butLast (l2, x, l3);
         (future(x), future(l1))
      end
   | butLast ([], x, l1) = raise Empty
val x = [1, 2, 3, 4];
inspect (butLast(x, promise(), promise()));

(* amortized constant-time ephemeral queue *)
datatype 'a queue = Queue of 'a list * 'a list

fun newQueue () = Queue(nil, nil)

fun checkQ (Queue(nil, r)) = Queue(reverse r, nil)
  | checkQ q = q

fun insertQ (Queue(f, r), x) = checkQ(Queue(f, x::r))

fun deleteQ (Queue(f::fs, r), px) =
      let
         val _ = fulfill(px, f)
      in
         checkQ(Queue(fs, r))
      end
  | deleteQ (Queue([], r), px) = raise Empty

fun isEmpty' (Queue(f::fs, r)) = false
  | isEmpty' (Queue([], r))    = true

val q1 = newQueue()
val q2 = insertQ(q1, "peter")
val q3 = insertQ(q2, "paul");
val p4 = promise()
val q4 = deleteQ(q3, p4);
inspect (future p4);
val q5 = insertQ(q4, "mary")
val p6 = promise()
val q6 = deleteQ(q5, p6);
inspect (future p6);
val p7 = promise()
val q7 = deleteQ(q6, p7);
inspect (future p7);

(* Worst-case constant-time ephemeral queue *)
datatype 'a queue = Queue of int * 'a promise list promise * 'a promise list promise

fun newQueue () =
   let
      val x = promise()
   in
      Queue(0, x, x)
   end

fun insertQ (Queue(n, s, e), x) if (n >= 0) =
      let
         val e1 = promise()
         val px = promise()
      in
         fulfill(px, x);
         fulfill(e, px::(future e1));
         Queue(n+1, s, e1)
      end
  | insertQ (Queue(n, s, e), x) if (n = ~1) =
      let
         val e1 = promise()
         val px = hd(future e)
      in
         fulfill(px, x);
         Queue(n+1, e1, e1)
      end
  | insertQ (Queue(n, s, e), x) =
      let
         val e1 = promise()
         val px = hd(future e)
      in
         fulfill(px, x);
         fulfill(e1, tl(future e));
         Queue(n+1, s, e1)
      end

fun deleteQ (Queue(n, s, e), px) if (n <= 0) =
      let
         val s1 = promise()
      in
         fulfill(s, px::(future s1));
         Queue(n-1, s1, e)
      end
  | deleteQ (Queue(n, s, e), px) if (n = 1) =
      let
         val s1 = promise()
      in
         fulfill(px, future (hd(future s)));
         Queue(n-1, s1, s1)
      end
  | deleteQ (Queue(n, s, e), px) =
      let
         val s1 = promise()
      in
         fulfill(px, future (hd(future s)));
         fulfill(s1, tl(future s));
         Queue(n-1, s1, e)
      end

fun isEmpty' (Queue(n, s, e)) = (n = 0)

val q1 = newQueue()
val q2 = insertQ(q1, "peter")
val q3 = insertQ(q2, "paul")
val p4 = promise()
val q4 = deleteQ(q3, p4);
inspect (future p4);
val p5 = promise()
val q5 = deleteQ(q4, p5);
inspect (future p5);
val p6 = promise()
val q6 = deleteQ(q5, p6);
inspect (future p6);
val q7 = insertQ(q6, "mary");

(* persistent queues *)
fun forkD (d, e, f) =
   let
      val (d1, _) = d
      val (e1, e0) = e
      val (f1, f0) = f
   in
(* need to figure out what {Append D1 E0 E1} does in Oz
      appendD(appendD(d1, e0), e1);
      appendD(appendD(d1, f0), f1);
*)
      d
   end

fun forkQ (Queue(n, s, e)) =
      let
         val s1 = promise()
         val s2 = promise()
         val e1 = promise()
         val e2 = promise()
         val q1 = Queue(n, s1, e1)
         val q2 = Queue(n, s2, e2)
      in
         forkD((s, e), (s1, e1), (s2, e2));
         (q1, q2)
      end
  | forkQ (_) = raise Empty;

val q1 = newQueue()
val q2 = insertQ(q1, "peter")
val (qa, qb) = forkQ(q2);
inspect qa;
inspect qb;

(* 3.4.6.2 Trees - Storing information in trees *)
datatype ('a, 'b) obtree = Leaf
                         | Tree of 'a * 'b * ('a, 'b) obtree * ('a, 'b) obtree

val xtree = Tree(#"c", 10, Tree(#"a", 20, Leaf, Leaf), Tree(#"e", 30, Leaf, Leaf));

fun lookupOBT (x, Leaf, lt) = NONE
  | lookupOBT (x, Tree(y, v, t1, t2), lt) =
      if (lt(x, y))
         then lookupOBT(x, t1, lt)
         else
            if (lt(y, x))
               then lookupOBT(x, t2, lt)
               else SOME v;

inspect (lookupOBT(#"c", xtree, op<));
inspect (lookupOBT(#"a", xtree, op<));
inspect (lookupOBT(#"e", xtree, op<));
inspect (lookupOBT(#"b", xtree, op<));

fun lookupOBT (x, Leaf, lt) = NONE
  | lookupOBT (x, Tree(y, v, t1, t2), lt) if (lt(x, y)) =
      lookupOBT(x, t1, lt)
  | lookupOBT (x, Tree(y, v, t1, t2), lt) if (lt(y, x)) =
      lookupOBT(x, t2, lt)
  | lookupOBT (x, Tree(y, v, t1, t2), lt) = SOME v;

inspect (lookupOBT(#"c", xtree, op<));
inspect (lookupOBT(#"a", xtree, op<));
inspect (lookupOBT(#"e", xtree, op<));
inspect (lookupOBT(#"b", xtree, op<));

fun insertOBT (x, v, Leaf, lt) = Tree(x, v, Leaf, Leaf)
  | insertOBT (x, v, Tree(y, w, t1, t2), lt) if (lt(x, y)) =
      Tree(y, w, insertOBT(x, v, t1, lt), t2)
  | insertOBT (x, v, Tree(y, w, t1, t2), lt) if (lt(y, x)) =
      Tree(y, w, t1, insertOBT(x, v, t2, lt))
  | insertOBT (x, v, Tree(y, w, t1, t2), lt) =
      Tree(x, v, t1, t2);

inspect (insertOBT(#"b", 15, xtree, op<));

(* 3.4.6.3 Trees - Deletion and tree reorganization *)
fun deleteSubTree (x, Leaf, lt) = Leaf
  | deleteSubTree (x, Tree(y, w, t1, t2), lt) if (lt(x, y)) =
      Tree(y, w, deleteSubTree(x, t1, lt), t2)
  | deleteSubTree (x, Tree(y, w, t1, t2), lt) if (lt(y, x)) =
      Tree(y, w, t1, deleteSubTree(x, t2, lt))
  | deleteSubTree (x, Tree(y, w, t1, t2), lt) = Leaf;

inspect (deleteSubTree(#"c", xtree, op<));

fun removeSmallest (Leaf) = NONE
  | removeSmallest (Tree(y, v, t1, t2)) =
      let
         val tx = removeSmallest(t1)
      in
         case tx of
             NONE => SOME (y, v, t2)
           | SOME (yp, vp, tp) => SOME (yp, vp, Tree(y, v, tp, t2))
      end

fun deleteOBT (x, Leaf, lt) = Leaf
  | deleteOBT (x, Tree(y, w, t1, t2), lt) if (lt(x, y)) =
      Tree(y, w, deleteOBT(x, t1, lt), t2)
  | deleteOBT (x, Tree(y, w, t1, t2), lt) if (lt(y, x))=
      Tree(y, w, t1, deleteOBT(x, t2, lt))
  | deleteOBT (x, Tree(y, w, t1, t2), lt) =
      let
         val tx = removeSmallest(t2)
      in
         case tx of
             NONE => t1
           | SOME (yp, vp, tp) => Tree(yp, vp, t1, tp)
      end;

inspect (deleteOBT(#"c", xtree, op<));

(* 3.4.6.4 Trees - Tree traversal *)

(* Depth-first traversal *)
fun dfs (Leaf) = ()
  | dfs (Tree(key, v, l, r)) = (inspect (key:char, v:int); dfs l; dfs r);

dfs(xtree);

fun dfsAccLoop (Leaf, s1, sn) = fulfill(sn, future s1)
  | dfsAccLoop (Tree(key, v, l, r), s1, sn) =
      let
         val s2 = promise()
         val s3 = promise()
      in
         fulfill(s2, (key, v)::(future s1));
         dfsAccLoop(l, s2, s3);
         dfsAccLoop(r, s3, sn)
      end
fun dfsAcc t =
   let
      val s1 = promise()
      val sn = promise()
   in
      fulfill(s1, nil);
      dfsAccLoop(t, s1, sn);
      reverse(future sn)
   end;

inspect (dfsAcc(xtree));

fun dfsAccLoop2 (Leaf, s1, sn) = fulfill(s1, future sn)
  | dfsAccLoop2 (Tree(key, v, l, r), s1, sn) =
      let
         val s2 = promise()
         val s3 = promise()
      in
         fulfill(s1, (key, v)::(future s2));
         dfsAccLoop2(l, s2, s3);
         dfsAccLoop2(r, s3, sn)
      end
fun dfsAcc2 t =
   let
      val s1 = promise()
      val sn = promise()
   in
      fulfill(sn, []);
      dfsAccLoop2(t, s1, sn);
      future s1
   end;

inspect (dfsAcc2(xtree));

(* Breath-first traversal *)
fun bfs t =
   let
      fun treeInsert (q, Leaf) = q
        | treeInsert (q, t) = insertQ(q, t)
      fun bfsQueue q1 =
         if (isEmpty' q1)
            then ()
            else
               let
                  val x = promise()
                  val q2 = promise()
               in
                  fulfill(q2, deleteQ(q1, x));
                  case future x of
                      Tree(key, v, l, r) => (
                        inspect (key:char, v:int);
                        bfsQueue(treeInsert(treeInsert(future q2, l), r)))
                    | Leaf => ()
               end
   in
      bfsQueue(treeInsert(newQueue(), t))
   end;
bfs(xtree);

fun bfsAcc t =
   let
      fun treeInsert (q, Leaf) = q
        | treeInsert (q, t) = insertQ(q, t)
      fun bfsQueue (q1, s1, sn) =
         if (isEmpty' q1)
            then fulfill(s1, future sn)
            else
               let
                  val x = promise()
                  val q2 = promise()
                  val s2 = promise()
               in
                  fulfill(q2, deleteQ(q1, x));
                  case future x of
                      Tree(key, v, l, r) => (
                        fulfill(s1, (key, v)::(future s2));
                        bfsQueue(treeInsert(treeInsert(future q2, l), r), s2, sn))
                    | Leaf => ()
               end
      val s1 = promise()
      val sn = promise()
   in
      fulfill(sn, nil);
      bfsQueue(treeInsert(newQueue(), t), s1, sn);
      future s1
   end;

inspect (bfsAcc(xtree));

fun dfs t =
   let
      fun treeInsert (s, Leaf) = s
        | treeInsert (s, t) = t::s
      fun dfsStack (Tree(key, v, l, r)::s) = (
         inspect (key:char, v:int);
         dfsStack(treeInsert(treeInsert(s, r), l)))
       | dfsStack _ = ()
   in
      dfsStack(treeInsert(nil, t))
   end;

dfs(xtree);

(* 3.4.7 Trees - Drawing Trees *)

(* Don't like the Oz Adjoin function - so I just attached the coordinates directly in the tree *)
datatype ('a, 'b, 'c) obtree = Leaf
                             | Tree of { key   : 'a,
                                         value : 'b,
                                         x     : 'c promise,
                                         y     : 'c promise,
                                         left  : ('a, 'b, 'c) obtree,
                                         right : ('a, 'b, 'c) obtree }

val scale = 30

fun depthFirst (Tree{x, y, left=Leaf, right=Leaf, ...}, level, leftLim, rootX, rightLim) =
      let
      in
         fulfill(x, future rootX);
         fulfill(rootX, future rightLim);
         fulfill(rightLim, future leftLim);
         fulfill(y, scale * level)
      end
  | depthFirst (Tree{x, y, left, right=Leaf, ...}, level, leftLim, rootX, rightLim) =
      let
      in
         fulfill(x, future rootX);
         fulfill(y, scale * level);
         depthFirst(left, level+1, leftLim, rootX, rightLim)
      end
  | depthFirst (Tree{x, y, left=Leaf, right, ...}, level, leftLim, rootX, rightLim) =
      let
      in
         fulfill(x, future rootX);
         fulfill(y, scale * level);
         depthFirst(right, level+1, leftLim, rootX, rightLim)
      end
  | depthFirst (Tree{x, y, left, right, ...}, level, leftLim, rootX, rightLim) =
      let
         val lRootX = promise()
         val rRootX = promise()
         val lRightLim = promise()
         val rLeftLim = promise()
      in
         fulfill(y, scale * level);
         depthFirst(left, level+1, leftLim, lRootX, lRightLim);
         fulfill(rLeftLim, scale + (future lRightLim));
         depthFirst(right, level+1, rLeftLim, rRootX, rightLim);
         fulfill(x, future rootX);
         fulfill(rootX, (future lRootX + future rRootX) div 2)
      end
  | depthFirst (Leaf, _, _, _, _) = ();

val xtree = Tree{key=(#"a"), value=111, x=promise(), y=promise(),
               left=Tree{key=(#"b"), value=55, x=promise(), y=promise(),
                  left=Tree{key=(#"x"), value=100, x=promise(), y=promise(),
                     left=Tree{key=(#"z"), value=56, x=promise(), y=promise(),
                        left=Leaf,
                        right=Leaf},
                     right=Tree{key=(#"w"), value=23, x=promise(), y=promise(),
                        left=Leaf,
                        right=Leaf}},
                  right=Tree{key=(#"y"), value=105, x=promise(), y=promise(),
                     left=Leaf,
                     right=Tree{key=(#"r"), value=77, x=promise(), y=promise(),
                        left=Leaf,
                        right=Leaf}}},
               right=Tree{key=(#"c"), value=123, x=promise(), y=promise(),
                  left=Tree{key=(#"d"), value=119, x=promise(), y=promise(),
                     left=Tree{key=(#"g"), value=44, x=promise(), y=promise(),
                        left=Leaf,
                        right=Leaf},
                     right=Tree{key=(#"h"), value=50, x=promise(), y=promise(),
                        left=Tree{key=(#"i"), value=5, x=promise(), y=promise(),
                           left=Leaf,
                           right=Leaf},
                        right=Tree{key=(#"j"), value=6, x=promise(), y=promise(),
                           left=Leaf,
                           right=Leaf}}},
                  right=Tree{key=(#"e"), value=133, x=promise(), y=promise(),
                     left=Leaf,
                     right=Leaf}}}

val leftLim = promise();
fulfill(leftLim, scale);
depthFirst(xtree, 1, leftLim, promise(), promise());
inspect xtree;

(* 3.4.8 Trees - Parsing *)
(* Not finished - skipping over this section for the time being *)
fun isInt   s = foldl (fn (x,y) => Char.isDigit(x)    andalso y) true (explode (future s))
fun isIdent s = foldl (fn (x,y) => Char.isAlphaNum(x) andalso y) true (explode (future s))

fun id (s1, sn) =
   let
      val x = promise()
   in
      fulfill(x, hd (future s1));
      (x)
   end

fun cop y =
   case y of
       "<"  => true
     | ">"  => true
     | "=<" => true
     | ">=" => true
     | "==" => true
     | "!=" => true
     | _    => false

fun eop y =
   case y of
       "+"  => true
     | "-"  => true
     | _    => false

fun top y =
   case y of
       "*"  => true
     | "/"  => true
     | _    => false

fun sequence (nonterm, sep, s1, sn) =
   let
      val s2 = promise()
      val s3 = promise()
      val x1 = nonterm(s1, s2)
      val t = hd(future s2)
   in
      fulfill(s3, tl(future s2));
      if (sep(t))
         then
            let
               val x2 = sequence(nonterm, sep, s3, sn)
            in
               (* T(X1 X2) in Oz - not sure how to make consisten return type *)
               (x1)
            end
         else
            let
               val _ = fulfill(s2, future sn)
            in
               (x1)
            end
   end

fun comp (s1, sn) = sequence(expr, cop, s1, sn)
and expr (s1, sn) = sequence(term, eop, s1, sn)
and term (s1, sn) = sequence(fact, top, s1, sn)
and fact (s1, sn) =
   let
      val t = promise()
      val s2 = promise()
   in
      fulfill(t, hd(future s1));
      fulfill(s2, tl(future s1));
      if (isInt(t) orelse isIdent(t))
         then
            let
               val _ = fulfill(sn, future s2)
            in
               (t)
            end
         else
            let
               val e = promise()
               val s4 = promise()
               val s3 = promise()
            in
               (* S1 = '('|S4 - not quite there *)
               fulfill(s4, tl(future s1));
               e = expr(s4, s3);
               (* S3 = ')'|Sn - not quite there *)
               fulfill(s3, tl(future sn));
               (e)
            end
   end

fun prog (s1, sn) =
   let
      val y = promise()
      val z = promise()
      val s2 = promise()
      val s3 = promise()
      val s4 = promise()
      val s5 = promise()
   in
      fulfill(s1, "program"::(future s2));
      fulfill(y, id(s2, 34));
      fulfill(s3, ";"::(future s4))
   end

(* Here's the Oz code (unverified)
   declare
      fun {IsIdent X} { IsAtom X } end
      fun {Id S1 Sn} X in S1=X|Sn true={IsIdent X} X end
      fun {COP Y}
         Y=='<'  orelse Y=='>'  orelse Y=='=<' orelse
         Y=='>=' orelse Y=='==' orelse Y=='!='
      end
      fun {EOP Y} Y=='+' orelse Y=='-' end
      fun {TOP Y} Y=='*' orelse Y=='/' end
      fun {Sequence NonTerm Sep S1 Sn}
      X1 S2 T S3 in
         X1={NonTerm S1 S2}
         S2=T|S3
         if {Sep T} then X2 in
            X2={Sequence NonTerm Sep S3 Sn}
            T(X1 X2)       % Dynamic Record Creation
         else
            S2=Sn
            X1
         end
      end
      fun {Comp S1 Sn} {Sequence Expr COP S1 Sn} end
      fun {Expr S1 Sn} {Sequence Expr EOP S1 Sn} end
      fun {Term S1 Sn} {Sequence Expr TOP S1 Sn} end
      fun {Fact S1 Sn}
      T|S2=S1 in
         if {IsInt T} orelse {IsIdent T} then
            S2=Sn
            T
         else E S2 S3 in
            S1='('|S2
            E={Expr S2 S3}
            S3=')'|Sn
            E
         end
      end
      fun {Stat S1 Sn}
      T|S2=S1 in
         case T
         of begin then
            {Sequence Stat fun  {$ X} X==';' end S2 'end'|Sn}
         [] 'if' then C X1 X2 S3 S4 S5 S6 in
            {Comp C S2 S3}
            S3='then'|S4
            X1={Stat S4 S5}
            S5='else'|S6
            X2={Stat S4 S5}
            'if'(C X1 X2)
         [] while then C X S3 S4 in
            C={Comp S2 S3}
            S3='do'|S4
            X={Stat S4 Sn}
            while(C X)
         [] read then I in
            I={Id S2 Sn}
            read(I)
         [] write then E in
            E={Expr S2 Sn}
            write(E)
         elseif {IsIdent T} then E S3 in
            S2=':='|S3
            E={Expr S3 Sn}
            assign(T E)
         else
            S1=Sn
            raise error(S1) end
         end
      end
      fun {Prog S1 Sn}
      Y Z S2 S3 S4 S5 in
         S1=program|S2
         Y={Id S2 S3}
         S3=';'|S4
         Z={Stat S2 S5}
         S5='end'|Sn
         prog(Y Z)
      end
      declare A Sn in
         A = {Prog
               [program foo ';'
                  while a '+' 3 '<'b 'do' b ':=' b '+' 1 'end']
               Sn}
      {Browse A}
      % local R={MakeRecord T [1 2]} in X1=R.1 X2=R.2 R end
*)

(* 3.5.1 Time and space efficiency - Execution time *)

fun append' (nil, ys)   = ys
  | append' (x::xs, ys) = x::append'(xs, ys)

fun append' (nil, ys, zs)   = fulfill(zs, ys)
  | append' (x::xr, ys, zs) =
      let
         val zr = promise()
      in
         fulfill(zs, x::(future zr));
         append'(xr, ys, zr)
      end

fun shiftLeft []      = [0]
  | shiftLeft (n::ns) = n::shiftLeft(ns);
fun shiftRight ns = 0::ns;
fun addList [] _ = []
  | addList _ [] = []
  | addList (n1::ns1) (n2::ns2) = (n1 + n2)::(addList ns1 ns2)

fun fastPascal 1 = [1]
  | fastPascal n =
      let
         val ns = fastPascal(n-1)
      in
         addList (shiftLeft ns) (shiftRight ns)
      end

fun mergesort nil = nil
  | mergesort (x::nil) = [x]
  | mergesort xs =
      let
         val (ys, zs) = split xs
      in
         merge(mergesort ys, mergesort zs)
      end;

(* 3.6.1 Higher-order programming - Basic operations *)
let
   val a = 1.0
   val b = 3.0
   val c = 2.0
   val d = b*b - 4.0*a*c
   val realSol = promise()
   val x1 = promise()
   val x2 = promise()
in
   if (d >= 0.0)
      then (
         fulfill(realSol, true);
         fulfill(x1, (~b + Math.sqrt(d))/(2.0*a));
         fulfill(x2, (~b - Math.sqrt(d))/(2.0*a))
      )
      else (
         fulfill(realSol, false);
         fulfill(x1, ~b/(2.0*a));
         fulfill(x2, Math.sqrt(d)/(2.0*a))
     )
end;

fun quadraticEquation (a, b, c) =
   let
      val d = b*b - 4.0*a*c
   in
      if (d >= 0.0)
         then (true, (~b + Math.sqrt(d))/(2.0*a), (~b - Math.sqrt(d))/(2.0*a))
         else (false, ~b/(2.0*a), Math.sqrt(d)/(2.0*a))
   end;

inspect (quadraticEquation(1.0, 3.0, 2.0));

fun sumList nil     = 0
  | sumList (x::xs) = x + sumList(xs)

fun foldr' nil     f u = u
  | foldr' (x::xs) f u = f (x, foldr' xs f u)

fun sumList xs =
   foldr' xs (fn (x, y) => x + y) 0

fun prodList xs =
   foldr' xs (fn (x, y) => x * y) 0

fun some xs =
   foldr' xs (fn (x, y) => x orelse y) false

fun genericMergeSort f xs =
   let
      fun merge (nil, ys) = ys
        | merge (xs, nil) = xs
        | merge (x::xr as xs, y::yr as ys) =
            if f(x, y)
               then x::merge(xr, ys)
               else y::merge(xs, yr)
      fun mergesort nil      = nil
        | mergesort (x::nil) = [x]
        | mergesort xs =
            let
               val (ys, zs) = split xs
            in
               merge(mergesort ys, mergesort zs)
            end
   in
      mergesort xs
   end

fun mergesort xs = genericMergeSort (fn (a, b) => a < b)  xs

fun makeSort f = genericMergeSort f

(* 3.6.2 Higher-order programming - Loop abstractions *)
fun for a b s f =
   let
      fun loopup c if (c <= b) = (f c; loopup (c+s))
        | loopup c = ()
      fun loopdown c if (c >= b) = (f c; loopdown (c+s))
        | loopdown c = ()
   in
      if (s > 0)
         then loopup a
         else
            if (s < 0)
               then loopdown a
               else ()
   end;

for 1 10 1 inspect;
for 10 1 ~2 inspect;

fun forall nil f = ()
  | forall (x::xs) f = (f x; forall xs f);

forall [#"a",#"b",#"c"] inspect;

fun foracc inx a b s f =
   let
      fun loopup (c, inx) if (c <= b) = loopup(c+s, f(inx, c))
        | loopup (c, inx) = inx
      fun loopdown (c, inx) if (c <= b) = loopdown(c+s, f(inx, c))
        | loopdown (c, inx) = inx
   in
      if (s > 0)
         then loopup(a, inx)
         else
            if (s < 0)
               then loopup(a, inx)
               else raise Domain
   end;

inspect (foracc 0 1 10 1 (fn (x,y) => x+y));

fun forallacc inx nil f     = inx
  | forallacc inx (x::xs) f = forallacc (f(inx, x)) xs f;

inspect (forallacc 0 [1,2,3,4] (fn (x,y) => x+y));

fun foldl' f u nil     = u
  | foldl' f u (x::xs) = foldl' f (f(u,x)) xs;

inspect (foldl' (fn (x,y) => x+y) 0 [1,2,3,4]);

fun foldr' f u xs =
   let
      fun loop (u, nil)   = u
        | loop (u, x::xs) = loop(f(u,x), xs)
   in
      loop(u, reverse xs)
   end;

inspect (foldr' (fn (x,y) => x+y) 0 [1,2,3,4]);

(* foldr that doesn't require a reverse *)
fun foldr' f u nil     = u
  | foldr' f u (x::xs) = f(x, foldr' f u xs);

inspect (foldr' (fn (x,y) => x+y) 0 [1,2,3,4]);

(* 3.6.3 Higher-order programming - Linquistic support for loops *)

(* Note: ML does not sport linguistic support for declarative loops *)
val ps = {name="hello", price=2000, coordinates=(1,2)} ::
         {name="alice", price=200,  coordinates=(3,4)} :: []

(* pattern matching loop via recursive function *)
fun patternloop nil = ()
  | patternloop ({name=n, price=p, coordinates=c}::xs) = (
      if (p < 1000)
         then inspect (n:string)
         else ();
      patternloop(xs));

patternloop(ps);

(* pattern matching loop via anonymous recursive function *)
(rec f => fn nil => ()
    | ({name=n, price=p, coordinates=c}::xs) => (
         if (p < 1000)
            then inspect (n:string)
            else ();
         f(xs)))
   ps;

(* pattern matching loop via while state loop *)
let
   val xr = ref ps
in
   while (null(!xr)) do
      let
         val {name=n, price=p, coordinates=c} = hd (!xr)
      in
         if (p < 1000)
            then inspect n
            else ();
         xr := tl (!xr)
      end
end;

(* collecting via recursive function *)
fun collectloop (i, b, f) if (i > b) = []
  | collectloop (i, b, f) = (f i)@collectloop(i+1, b, f)

val c = fn i => if (i mod 2 <> 0) andalso (i mod 3 <> 0) then [i] else [];
inspect (collectloop(1, 1000, c));

(* using foracc iterator *)
inspect (foracc [] 1 1000 1 (fn (a, i) => a @ c(i)));

(* collection via nested recursive functions *)
fun collectnested i if (i > 1000) = []
  | collectnested i =
      let
         fun collectinner j if (j > 10) = []
           | collectinner j =
               if (i mod j = 0)
                  then [(i, j)] @ collectinner(j+1)
                  else collectinner(j+1)
      in
         if (i mod 2 <> 0) andalso (i mod 3 <> 0)
            then (collectinner 2) @ collectnested(i+1)
            else collectnested(i+1)
      end;
inspect (collectnested 1);

(* 3.6.4.1 Higher-order programming - List-based techniques *)
fun map' f nil     = nil
  | map' f (x::xs) = (f x)::(map' f xs);

inspect (map' (fn i => i*i) [1,2,3]);

fun map' f xs =
   foldr' (fn (i, a) => (f i)::a) nil xs;

inspect (map' (fn i => i*i) [1,2,3]);

fun filter' f nil = nil
  | filter' f (x::xs) =
      if (f x)
         then x::(filter' f xs)
         else (filter' f xs);

inspect (filter' (fn a => (a < 3)) [1,2,3,4]);

fun filter' f xs =
   foldr' (fn (i, a) => if (f i) then i::a else a) nil xs;

inspect (filter' (fn a => (a < 3)) [1,2,3,4]);

fun foldr' f u xs =
   #2(iterate
      (fn (xr, a) => (tl xr, f (hd xr, a)))
      (fn (xr, a) => null xr)
      (reverse xs, u));

inspect (foldr' (fn (x,y) => x+y) 0 [1,2,3,4]);

(* 3.6.4.2 Higher-order programming - Tree-based techniques *)

datatype 'a tree = Tree of {node:'a, sons:'a tree list}

val ts = Tree{node=1,
              sons=[Tree{node=2, sons=nil},
                    Tree{node=3, sons=[Tree{node=4, sons=nil}]}]}

fun dfs (Tree{node=n, sons=xs}) = (
      inspect (n:int);
      forall xs dfs);

dfs ts;

fun visitnodes f (t as Tree{sons=xs, ...}) = (
      f t;
      forall xs (visitnodes f));

visitnodes (fn (Tree{node=n, ...}) => inspect n) ts;

fun visitlinks f (t as Tree{sons=xs, ...}) =
      forall xs (f t; visitnodes f);

visitlinks (fn Tree{node=n, ...} => inspect n) ts;

fun foldtreer tf lf u nil = u
  | foldtreer tf lf u (x::xs) =
      lf(foldtree tf lf u x, foldtreer tf lf u xs)
and foldtree tf lf u (Tree{node=n, sons=xs}) =
      tf(n, (foldtreer tf lf u xs))

fun add (a, b) = a + b;

inspect (foldtree add add 0 ts);

(* 3.6.6 Higher-order programming - Currying *)

fun max' x y =
   if (x >= y) then x else y

fun max' x =
   fn y => if (x >= y) then x else y;

inspect ((max' 10) 20);

val lowerbound10 = max' 10

fun lowerbound10 y =
   max' 10 y

(* 3.7.1 Abstract data types - A declarative stack *)
signature STACK' =
   sig
      type t
      type stack
      val newStack : unit -> stack
      val push     : stack * t -> stack
      val pop      : stack * t promise -> stack
      val isEmpty  : stack -> bool
   end

structure Stack' : STACK' =
   struct
      type t = int
      type stack = t list
      fun newStack () = nil
      fun push (s, e) = e::s
      fun pop (nil, e) = raise Empty
        | pop (x::xs, e) = (
            fulfill(e, x);
            xs)
      fun isEmpty nil = true
        | isEmpty _ = false
   end;

let
   val x = 123
   val px = promise()
   val sn = Stack'.newStack()
   val s0 = Stack'.push(sn, x)
   val s1 = Stack'.pop(s0, px)
in
   assert (Stack'.isEmpty sn) of true;
   assert (sn = s1) of true;
   assert (x = future px) of true;
   assert (Stack'.pop(sn, px); false) handle Empty => true of true
end;

structure Stack' : STACK' =
   struct
      type t = int
      datatype stack = EmptyStack
                     | StackCons of t * stack
      fun newStack () = EmptyStack
      fun push (s, e) = StackCons(e, s)
      fun pop (EmptyStack, e) = raise Empty
        | pop (StackCons (x, s), e) = (
            fulfill(e, x);
            s)
      fun isEmpty EmptyStack = true
        | isEmpty _ = false
   end;

let
   val x = 123
   val px = promise()
   val sn = Stack'.newStack()
   val s0 = Stack'.push(sn, x)
   val s1 = Stack'.pop(s0, px)
in
   assert (Stack'.isEmpty sn) of true;
   assert (sn = s1) of true;
   assert (x = future px) of true;
   assert (Stack'.pop(sn, px); false) handle Empty => true of true
end;

(* a functional programming look *)
signature STACK' =
   sig
      type t
      type stack
      val newStack : unit -> stack
      val push     : stack * t -> stack
      val pop      : stack -> stack * t
      val isEmpty  : stack -> bool
   end

structure Stack' : STACK' =
   struct
      type t = int
      type stack = t list
      fun newStack () = nil
      fun push (s, e) = e::s
      fun pop nil = raise Empty
        | pop (x::xs) = (xs, x)
      fun isEmpty nil = true
        | isEmpty _ = false
   end;

let
   val x = 123
   val sn = Stack'.newStack()
   val s0 = Stack'.push(sn, x)
   val (s1, y) = Stack'.pop(s0)
in
   assert (Stack'.isEmpty sn) of true;
   assert (sn = s1) of true;
   assert (x = y) of true;
   assert (Stack'.pop(sn); false) handle Empty => true of true
end;

structure Stack' : STACK' =
   struct
      type t = int
      datatype stack = EmptyStack
                     | StackCons of t * stack
      fun newStack () = EmptyStack
      fun push (s, e) = StackCons(e, s)
      fun pop (EmptyStack) = raise Empty
        | pop (StackCons(x, s)) = (s, x)
      fun isEmpty EmptyStack = true
        | isEmpty _ = false
   end;

let
   val x = 123
   val sn = Stack'.newStack()
   val s0 = Stack'.push(sn, x)
   val (s1, y) = Stack'.pop(s0)
in
   assert (Stack'.isEmpty sn) of true;
   assert (sn = s1) of true;
   assert (x = y) of true;
   assert (Stack'.pop(sn); false) handle Empty => true of true
end;

(* 3.7.2 Abstract data types - A declarative dictionary *)
signature DICTIONARY =
   sig
      type keytype
      type valtype
      type dictionary
      val newDictionary : unit -> dictionary
      val put           : dictionary * keytype * valtype -> dictionary
      val get           : dictionary * keytype -> valtype option
      val condGet       : dictionary * keytype * valtype -> valtype
      val domain        : dictionary -> keytype list
   end

structure Dictionary : DICTIONARY =
   struct
      type keytype = string
      type valtype = int
      type dictionary = (keytype * valtype) list
      fun newDictionary () = nil
      fun put (nil, key:keytype, value:valtype)        = [(key, value)]
        | put ((k, v)::ds, key, value) if (k = key) = (key, value)::ds
        | put ((k, v)::ds, key, value) if (k > key) = (key, value)::(k, v)::ds
        | put ((k, v)::ds, key, value)                 = (k, v)::put(ds, key, value)
      fun get (nil, key:keytype)                = NONE
        | get ((k, v)::ds, key) if (k > key) = NONE
        | get ((k, v)::ds, key) if (k = key) = SOME v
        | get ((k, v)::ds, key)                 = get(ds, key)
      fun condGet (nil, key:keytype, default:valtype)        = default
        | condGet ((k, v)::ds, key, default) if (k > key) = default
        | condGet ((k, v)::ds, key, _) if (k = key)       = v
        | condGet ((k, v)::ds, key, default)                 = condGet(ds, key, default)
      fun domain ds = map' (fn (x,y) => x) ds
   end

structure Dictionary : DICTIONARY =
   struct
      type keytype = string
      type valtype = int
      datatype dictionary = Leaf
                          | Tree of keytype * valtype * dictionary * dictionary
      fun newDictionary () = Leaf
      fun put (Leaf, key, value)                             = Tree(key, value, Leaf, Leaf)
        | put (Tree(k, v, l, r), key, value) if (key < k) = Tree(k, v, put(l, key, value), r)
        | put (Tree(k, v, l, r), key, value) if (key > k) = Tree(k, v, l, put(r, key, value))
        | put (Tree(k, v, l, r), key, value)                 = Tree(key, value, l, r)
      fun get (Leaf, key)                             = NONE
        | get (Tree(k, v, l, r), key) if (key < k) = get(l, key)
        | get (Tree(k, v, l, r), key) if (key > k) = get(r, key)
        | get (Tree(k, v, l, r), key)                 = SOME v
      fun condGet (Leaf, key, default)                             = default
        | condGet (Tree(k, v, l, r), key, default) if (key < k) = condGet(l, key, default)
        | condGet (Tree(k, v, l, r), key, default) if (key > k) = condGet(r, key, default)
        | condGet (Tree(k, v, l, r), key, default)                 = v
      fun domain ds =
         let
            fun domainD (Leaf, s1, sn) = fulfill(s1, future sn)
              | domainD (Tree(k, v, l, r), s1, sn) =
                  let
                     val s2 = promise()
                     val s3 = promise()
                  in
                     domainD(l, s1, s2);
                     fulfill(s2, k::(future s3));
                     domainD(r, s3, sn)
                  end
            val d = promise()
            val p = promise()
         in
            fulfill(p, nil);
            domainD(ds, d, p);
            future d
         end
   end

(* 3.7.3 Abstract data types - A word frequency application *)
fun wordChar c =
   (#"a" <= c andalso c <= #"z") orelse
   (#"A" <= c andalso c <= #"Z") orelse
   (#"0" <= c andalso c <= #"9")

fun stringToAtom pw = implode pw

fun wordToAtom pw =
   stringToAtom (List.rev pw)

fun incWord (d, w) =
   Dictionary.put(d, w, Dictionary.condGet(d, w, 0) + 1)

fun charsToWords (nil, nil) = nil
  | charsToWords (pw, nil) = [wordToAtom pw]
  | charsToWords (pw, c::cs) if (wordChar c) =
      charsToWords ((Char.toLower c)::pw, cs)
  | charsToWords (nil, c::cs) = charsToWords(nil, cs)
  | charsToWords (pw, c::cs) =
      (wordToAtom pw)::(charsToWords(nil, cs))

fun countWords (d, w::ws) = countWords(incWord(d, w), ws)
  | countWords (d, nil)   = d

fun wordFreq cs =
   countWords(Dictionary.newDictionary(), charsToWords(nil, cs));

let
   val t = "Oh my darling, oh my darling.  oh my darling Clementine." ^
           "She is lost and gone forever.  oh my darling Clementine."
in
   inspect (wordFreq(explode t))
end;

(* 3.7.5 Abstract data types - The declarative model with secure types *)
fun newName () = promise()
val s = [#"a", #"b", #"c"]
val key = newName()
val ss = fn k => if (k = key) then s else raise Match
val x = ss key

exception Wrapper
exttype 'a key
fun newWrapper () =
   let
      constructor Key of 'a : 'a key
      fun unKey (Key x) = x | unKey _ = raise Wrapper
   in
      (Key, unKey)
   end

val (wrap, unwrap) = newWrapper()
val ss = wrap "abc"
val s = unwrap ss

local
   val (wrap, unwrap) = newWrapper()
in
   fun newStack () = wrap nil
   fun push (s, e) = wrap(e::(unwrap s))
   fun pop (s, e) =
      case (unwrap s) of
          nil   => raise Empty
        | x::xs => (fulfill(e, x); wrap xs)
   fun isEmpty s = (unwrap s = nil)
end;

val p = promise();
newStack();
inspect (isEmpty(pop(push(push(newStack(), "abc"), "def"), p)));
inspect (future p);

(* 3.7.6 Abstract data types - A secure declarative dictionary *)
structure SecureDictionary : DICTIONARY =
   let
      val (wrap, unwrap) = newWrapper()
   in
      struct
         eqtype keytype = Dictionary.keytype
         eqtype valtype = Dictionary.valtype
         type dictionary = Dictionary.dictionary key
         fun newDictionary ()         = wrap(Dictionary.newDictionary())
         fun put (ds, k, v)           = wrap(Dictionary.put(unwrap ds, k, v))
         fun get (ds, k)              = Dictionary.get(unwrap ds, k)
         fun condGet (ds, k, default) = Dictionary.condGet(unwrap ds, k, default)
         fun domain ds                = Dictionary.domain(unwrap ds)
      end
   end

val ds = SecureDictionary.put(SecureDictionary.newDictionary(), "abc", 123);
inspect (SecureDictionary.domain(ds));

(* Note: Opaque signatures provide secure types without need for wrappers *)
structure Dictionary :> (DICTIONARY where type keytype = string
                                    where type valtype = int) =
   struct
      type keytype = string
      type valtype = int
      datatype dictionary = Leaf
                          | Tree of keytype * valtype * dictionary * dictionary
      fun newDictionary () = Leaf
      fun put (Leaf, key, value)                             = Tree(key, value, Leaf, Leaf)
        | put (Tree(k, v, l, r), key, value) if (key < k) = Tree(k, v, put(l, key, value), r)
        | put (Tree(k, v, l, r), key, value) if (key > k) = Tree(k, v, l, put(r, key, value))
        | put (Tree(k, v, l, r), key, value)                 = Tree(key, value, l, r)
      fun get (Leaf, key)                             = NONE
        | get (Tree(k, v, l, r), key) if (key < k) = get(l, key)
        | get (Tree(k, v, l, r), key) if (key > k) = get(r, key)
        | get (Tree(k, v, l, r), key)                 = SOME v
      fun condGet (Leaf, key, default)                             = default
        | condGet (Tree(k, v, l, r), key, default) if (key < k) = condGet(l, key, default)
        | condGet (Tree(k, v, l, r), key, default) if (key > k) = condGet(r, key, default)
        | condGet (Tree(k, v, l, r), key, default)                 = v
      fun domain ds =
         let
            fun domainD (Leaf, s1, sn) = fulfill(s1, future sn)
              | domainD (Tree(k, v, l, r), s1, sn) =
                  let
                     val s2 = promise()
                     val s3 = promise()
                  in
                     domainD(l, s1, s2);
                     fulfill(s2, k::(future s3));
                     domainD(r, s3, sn)
                  end
            val d = promise()
            val p = promise()
         in
            fulfill(p, nil);
            domainD(ds, d, p);
            future d
         end
   end

val ds = Dictionary.put(Dictionary.newDictionary(), "abc", 123);
inspect (Dictionary.domain(ds));

(* 3.8.1 Nondeclarative needs - Text input/output with a file *)
val infile = TextIO.openIn "foo.txt"
val s = explode(TextIO.input infile);
TextIO.closeIn infile;

val response = HttpClient.get(Url.fromString "http://localhost/");
inspect (#body response);

val outfile = TextIO.openOut "foo.txt";
TextIO.output(outfile, "This comes in the file.\n");
TextIO.output(outfile, "The result of 43*43 in " ^ Int.toString(43*43) ^ ".\n");
TextIO.output(outfile, "Strings are ok too.\n");
TextIO.closeOut outfile;

(* test of SecureDictionary with appropriate redefinitions from section 3.7.3 *)
fun incWord (d, w) = SecureDictionary.put(d, w, SecureDictionary.condGet(d, w, 0) + 1)
fun countWords (d, w::ws) = countWords(incWord(d, w), ws)
  | countWords (d, nil)   = d
fun wordFreq cs = countWords(SecureDictionary.newDictionary(), charsToWords(nil, cs))

val infile = TextIO.openIn "foo.txt"
val s = TextIO.input infile;
TextIO.closeIn infile;
val d = wordFreq(explode s)

val outfile = TextIO.openOut "wordfreq.txt";
map
   (fn k => TextIO.output(outfile, k^": "^Int.toString(SecureDictionary.condGet(d, k, 0))^"\n"))
   (SecureDictionary.domain d);
TextIO.closeOut outfile;

(* 3.8.2 Nondeclarative needs - Text input/output with a graphical user interface *)
datatype gtkglue = NOGLUE | N | S | W | E | NS | NW | NE | SW | SE | WE | NSW | NWE | SWE | NSWE
datatype gtk = GtkTD of gtk list
             | GtkLR of gtk list
             | GtkTitle of {text:string}
             | GtkLabel of {text:string}
             | GtkText of {object:(Gtk.object promise), tdscrollbar:bool, glue:gtkglue}
             | GtkButton of {text:string, action:(Gtk.callback_function), glue:gtkglue}
             | GtkGlue of gtkglue

fun gtkBuild d =
   let
      val window = Gtk.Window.new Gtk.WindowType.TOPLEVEL
      val destroyEvent = fn _ => OS.Process.exit OS.Process.success
      fun gtkPack (box, widget) =
         if (widget <> Gtk.NULL)
            then Gtk.Box.packStart(box, widget, false, false, 0)
            else ()
      fun build (GtkTD xs) =
            let
               val vBox = Gtk.VBox.new(false, 0)
            in
               map (fn x => let val widget = build x in gtkPack(vBox, widget) end) xs;
               vBox
            end
        | build (GtkLR xs) =
            let
               val hBox = Gtk.HBox.new(false, 0)
            in
               map (fn x => let val widget = build x in gtkPack(hBox, widget) end) xs;
               hBox
            end
        | build (GtkTitle {text}) =
            let
               val _ = Gtk.Window.setTitle(window, text)
            in
               Gtk.NULL
            end
        | build (GtkLabel {text}) =
            let
               val label = Gtk.Label.new text
            in
               label
            end
        | build (GtkText {object, tdscrollbar, glue}) =
            let
               val _ = fulfill(object, Gtk.TextView.new())
            in
               future object
            end
        | build (GtkButton {text, action, glue}) =
            let
               val button = Gtk.Button.newWithLabel text
            in
               Gtk.signalConnect(button, "clicked", action);
               button
            end
        | build (GtkGlue x) = Gtk.NULL
   in
      Gtk.signalConnect(window, "destroy-event", destroyEvent);
      Gtk.Container.setBorderWidth(window, 4);
      Gtk.Container.add(window, build d);
      window
   end

val pWindow = promise()
val textIn = promise()
val textOut = promise()
fun a1 _ =
   let
      val textBuffer    = Gtk.TextView.getBuffer(future textIn)
      val textIterStart = Gtk.TextIter.new()
      val textIterEnd   = Gtk.TextIter.new()
   in
      Gtk.TextBuffer.getBounds(textBuffer, textIterStart, textIterEnd);
      Gtk.TextBuffer.setText(
         Gtk.TextView.getBuffer(future textOut),
         Gtk.TextBuffer.getText(textBuffer, textIterStart, textIterEnd, false),
         Gtk.TextBuffer.getCharCount(textBuffer))
   end
fun a2 _ = Gtk.Widget.destroy(future pWindow) (* OS.Process.exit OS.Process.success *)
val d = GtkTD[
            GtkTitle {text="Simple text I/O interface"},
            GtkLR[GtkLabel {text="Input:"},
                  GtkText {object=textIn, tdscrollbar=true, glue=NSWE},
                  GtkGlue NSWE],
            GtkLR[GtkLabel {text="Output:"},
                  GtkText {object=textOut, tdscrollbar=true, glue=NSWE},
                  GtkGlue NSWE],
            GtkLR[GtkButton {text="Do It", action=a1, glue=NSWE},
                  GtkButton {text="Quit", action=a2, glue=NSWE}]
        ]
val window = gtkBuild(d);
fulfill(pWindow, window);
Gtk.Widget.showAll window;

val d = GtkTD[GtkButton {text="Ouch", action=(fn _ => inspect "ouch"), glue=NSWE}]
val window = gtkBuild(d);
Gtk.Widget.showAll window;

(* 3.8.3 Nondeclarative needs - Stateless data I/O with files *)
Pickle.save("Test."^Pickle.extension, pack (val x = "alice-ctm") : (val x:string));
structure Test = unpack Pickle.load("Test."^Pickle.extension) : (val x:string)
val x = Test.x;

signature FACT =
   sig
      val fact    : int -> int
      val f10     : int
      val f10gen1 : unit -> int
      val f10gen2 : unit -> int
      val fngen1  : int -> int
      val fngen2  : int -> int
   end

structure Fact : FACT =
   struct
      fun fact 0 = 1
        | fact n = n * fact(n-1)
      val f10 = fact 10
      val f10gen1 = fn () => f10
      val f10gen2 = fn () => fact 10
      fun fngen1 n = let val f = fact n in f end
      fun fngen2 n = fact n
   end;

Pickle.save("Fact."^Pickle.extension, pack Fact : FACT);
structure Fact' = unpack Pickle.load("Fact."^Pickle.extension) : FACT;

inspect (Fact'.fact 10);
inspect (Fact'.f10);
inspect (Fact'.f10gen1());
inspect (Fact'.f10gen2());
inspect (Fact'.fngen1 10);
inspect (Fact'.fngen2 10);

Pickle.save("Dictionary."^Pickle.extension, pack Dictionary : DICTIONARY);
structure Dictionary' = unpack Pickle.load("Dictionary."^Pickle.extension) : DICTIONARY;

(* 3.9.3 Program design in the small - Software components *)

structure MyList =
   let
      fun merge (nil, ys) = ys
        | merge (xs, nil) = xs
        | merge (x::xs, y::ys) =
            if (x < y)
               then x::merge(xs, y::ys)
               else y::merge(x::xs, ys)
      fun split nil = (nil, nil)
        | split (x::nil) = ([x], nil)
        | split (x::y::xs) =
            let
               val (ys, zs) = split xs
            in
               (x::ys, y::zs)
            end
      fun mergesort nil = nil
        | mergesort (x::nil) = [x]
        | mergesort xs =
            let
               val (ys, zs) = split xs
            in
               merge(mergesort ys, mergesort zs)
            end
   in
      struct
         fun append [] ys      = ys
           | append (x::xs) ys = x :: (append xs ys)
         fun sort xs = mergesort xs
         fun member (n, nil) = false
           | member (n, x::xs) = (n = x) orelse (member(n, xs))
      end
   end

functor MyListFunctor () =
   let
      fun merge (nil, ys) = ys
        | merge (xs, nil) = xs
        | merge (x::xs, y::ys) =
            if (x < y)
               then x::merge(xs, y::ys)
               else y::merge(x::xs, ys)
      fun split nil = (nil, nil)
        | split (x::nil) = ([x], nil)
        | split (x::y::xs) =
            let
               val (ys, zs) = split xs
            in
               (x::ys, y::zs)
            end
      fun mergesort nil = nil
        | mergesort (x::nil) = [x]
        | mergesort xs =
            let
               val (ys, zs) = split xs
            in
               merge(mergesort ys, mergesort zs)
            end
   in
      struct
         fun append [] ys      = ys
           | append (x::xs) ys = x :: (append xs ys)
         fun sort xs = mergesort xs
         fun member (n, nil) = false
           | member (n, x::xs) = (n = x) orelse (member(n, xs))
      end
   end

(* define export list through inline signature *)
functor MyListFunctor2 () :
   sig
      val append : 'a list -> 'a list -> 'a list
      val sort : int list -> int list
      val member : 'a * 'a list -> bool
   end =
   struct
      fun merge (nil, ys) = ys
        | merge (xs, nil) = xs
        | merge (x::xs, y::ys) =
            if (x < y)
               then x::merge(xs, y::ys)
               else y::merge(x::xs, ys)
      fun split nil = (nil, nil)
        | split (x::nil) = ([x], nil)
        | split (x::y::xs) =
            let
               val (ys, zs) = split xs
            in
               (x::ys, y::zs)
            end
      fun mergesort nil = nil
        | mergesort (x::nil) = [x]
        | mergesort xs =
            let
               val (ys, zs) = split xs
            in
               merge(mergesort ys, mergesort zs)
            end
      fun append [] ys      = ys
        | append (x::xs) ys = x :: (append xs ys)
      fun sort xs = mergesort xs
      fun member (n, nil) = false
        | member (n, x::xs) = (n = x) orelse (member(n, xs))
   end

(* 3.9.4 Program design in the small - Example of a standalone program *)
signature DICTIONARY =
   sig
      type keytype
      type valtype
      type dictionary
      val newDictionary : unit -> dictionary
      val put           : dictionary * keytype * valtype -> dictionary
      val condGet       : dictionary * keytype * valtype -> valtype
      val pairs         : dictionary -> (keytype * valtype) list
   end

structure Dictionary : DICTIONARY =
   struct
      type keytype = string
      type valtype = int
      datatype dictionary = Leaf
                          | Tree of keytype * valtype * dictionary * dictionary
      fun newDictionary () = Leaf
      fun put (Leaf, key, value)                             = Tree(key, value, Leaf, Leaf)
        | put (Tree(k, v, l, r), key, value) if (key < k) = Tree(k, v, put(l, key, value), r)
        | put (Tree(k, v, l, r), key, value) if (key > k) = Tree(k, v, l, put(r, key, value))
        | put (Tree(k, v, l, r), key, value)                 = Tree(key, value, l, r)
      fun condGet (Leaf, key, default)                             = default
        | condGet (Tree(k, v, l, r), key, default) if (key < k) = condGet(l, key, default)
        | condGet (Tree(k, v, l, r), key, default) if (key > k) = condGet(r, key, default)
        | condGet (Tree(k, v, l, r), key, default)                 = v
      fun pairs ds =
         let
            fun pairsD (Leaf, s1, sn) = fulfill(s1, future sn)
              | pairsD (Tree(k, v, l, r), s1, sn) =
                  let
                     val s2 = promise()
                     val s3 = promise()
                  in
                     pairsD(l, s1, s2);
                     fulfill(s2, (k, v)::(future s3));
                     pairsD(r, s3, sn)
                  end
            val d = promise()
            val p = promise()
         in
            fulfill(p, nil);
            pairsD(ds, d, p);
            future d
         end
   end

functor WordApp () =
   struct
      fun wordChar c =
         (#"a" <= c andalso c <= #"z") orelse
         (#"A" <= c andalso c <= #"Z") orelse
         (#"0" <= c andalso c <= #"9")

      fun stringToAtom pw = implode pw

      fun wordToAtom pw =
         stringToAtom (List.rev pw)

      fun incWord (d, w) =
         Dictionary.put(d, w, Dictionary.condGet(d, w, 0) + 1)

      fun charsToWords (nil, nil) = nil
        | charsToWords (pw, nil) = [wordToAtom pw]
        | charsToWords (pw, c::cs) if (wordChar c) =
            charsToWords ((Char.toLower c)::pw, cs)
        | charsToWords (nil, c::cs) = charsToWords(nil, cs)
        | charsToWords (pw, c::cs) =
            (wordToAtom pw)::(charsToWords(nil, cs))

      fun countWords (d, w::ws) = countWords(incWord(d, w), ws)
        | countWords (d, nil)   = d

      fun wordFreq cs =
         countWords(Dictionary.newDictionary(), charsToWords(nil, cs))

      (* Note: should probably get filename from stdin as per the oz code *)
      val infile = TextIO.openIn "foo.txt"
      val l = TextIO.input infile
      val _ = TextIO.closeIn infile
      val d = wordFreq(explode l)

      val s = genericMergeSort (fn ((_, a), (_, b)) => a > b) (Dictionary.pairs d)
      val h = promise()

      val des = GtkTD[GtkTitle {text="Word frequency count"},
                      GtkText {object=h, tdscrollbar=true, glue=NSWE}]
      val w = gtkBuild(des)
      val _ = Gtk.Widget.showAll w
      val t = foldl (fn ((k, v), x) => x ^ k ^ ": " ^ Int.toString(v) ^ " times\n") "" s
      val _ = Gtk.TextBuffer.setText(Gtk.TextView.getBuffer(future h), t, size t)

      val s1 = genericMergeSort (fn ((a, _), (b, _)) => a < b) (Dictionary.pairs d)
      val s2 = genericMergeSort (fn ((_, a), (_, b)) => a > b) (Dictionary.pairs d)
      val h1 = promise()
      val h2 = promise()
      val des = GtkTD[GtkTitle {text="Word frequency count"},
                      GtkText {object=h1, tdscrollbar=true, glue=NSWE},
                      GtkText {object=h2, tdscrollbar=true, glue=NSWE}]
      val w = gtkBuild(des)
      val _ = Gtk.Widget.showAll w
      val t1 = foldl (fn ((k, v), x) => x ^ k ^ ": " ^ Int.toString(v) ^ " times\n") "" s1
      val t2 = foldl (fn ((k, v), x) => x ^ k ^ ": " ^ Int.toString(v) ^ " times\n") "" s2
      val _ = Gtk.TextBuffer.setText(Gtk.TextView.getBuffer(future h1), t1, size t1)
      val _ = Gtk.TextBuffer.setText(Gtk.TextView.getBuffer(future h2), t2, size t2)
   end
structure _ = WordApp()




Chris Rathman / Chris.Rathman@tx.rr.com