home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / SML⁄NJ 93+ / Documentation / examples / textbooks / working / Imperative.ML < prev    next >
Encoding:
Text File  |  1995-12-30  |  6.5 KB  |  256 lines  |  [TEXT/R*ch]

  1. (**** ML Programs from the book
  2.  
  3.   ML for the Working Programmer
  4.   by Lawrence C. Paulson, Computer Laboratory, University of Cambridge.
  5.   (Cambridge University Press, 1991)
  6.  
  7. Copyright (C) 1991 by Cambridge University Press.
  8. Permission to copy without fee is granted provided that this copyright
  9. notice and the DISCLAIMER OF WARRANTY are included in any copy.
  10.  
  11. DISCLAIMER OF WARRANTY.  These programs are provided `as is' without
  12. warranty of any kind.  We make no warranties, express or implied, that the
  13. programs are free of error, or are consistent with any particular standard
  14. of merchantability, or that they will meet your requirements for any
  15. particular application.  They should not be relied upon for solving a
  16. problem whose incorrect solution could result in injury to a person or loss
  17. of property.  If you do use the programs or functions in such a manner, it
  18. is at your own risk.  The author and publisher disclaim all liability for
  19. direct, incidental or consequential damages resulting from your use of
  20. these programs or functions.
  21. ****)
  22.  
  23.  
  24. (**** Chapter 8.  IMPERATIVE PROGRAMMING IN ML ****)
  25.  
  26. (*** SEQUENCES USING REFERENCES ***)
  27.  
  28. signature SEQUENCE = 
  29.   sig
  30.   type 'a T
  31.   exception E
  32.   val empty: 'a T
  33.   val cons: '_a * (unit -> '_a T) -> '_a T
  34.   val null: 'a T -> bool
  35.   val hd: 'a T -> 'a
  36.   val tl: 'a T -> 'a T
  37.   val take: int * 'a T -> 'a list
  38.   val append: '_a T * '_a T -> '_a T
  39.   val map: ('a -> '_b) -> 'a T -> '_b T
  40.   val filter: ('_a -> bool) -> '_a T -> '_a T
  41.   val cycle: ((unit -> '_a T) -> '_a T) -> '_a T
  42.   end;
  43.  
  44.  
  45. functor ImpSeqFUN () : SEQUENCE =
  46.   struct
  47.   datatype 'a T  = Nil
  48.          | Cons of 'a * ('a T) ref
  49.          | Delayed of unit -> 'a T;
  50.  
  51.   exception E;
  52.  
  53.   fun delay xf = ref(Delayed xf);
  54.  
  55.   (*sequence "constructors" for export*)
  56.   val empty = Nil;
  57.   fun cons(x,xf) = Cons(x, delay xf);
  58.  
  59.   (*gets tail value, perhaps with the side effect of storing it*)
  60.   fun pull xp = 
  61.     case !xp of
  62.         Delayed f => let val s = f()
  63.              in  xp := s;  s  end
  64.       | s => s;
  65.  
  66.   (** these functions do not expect Delayed -- it is only permissible
  67.       in the tail of a Cons, where it is enclosed in a reference **)
  68.  
  69.   fun null Nil = true
  70.     | null (Cons _) = false;
  71.  
  72.   fun hd Nil = raise E
  73.     | hd (Cons(x,_)) = x;
  74.  
  75.   fun tl Nil = raise E
  76.     | tl (Cons(_,xp)) = pull xp;
  77.  
  78.   fun take (0, xq) = []
  79.     | take (n, Nil) = []
  80.     | take (n, Cons(x,xp)) = x :: take (n-1, pull xp);
  81.  
  82.   fun append (Nil,    yq) = yq
  83.     | append (Cons(x,xp), yq) =
  84.       Cons(x, delay(fn()=> append(pull xp, yq)));
  85.  
  86.   fun map f Nil  = Nil
  87.     | map f (Cons(x,xp)) = 
  88.           Cons(f x, delay(fn()=> map f (pull xp)));
  89.  
  90.   fun filter pred Nil = Nil
  91.     | filter pred (Cons(x,xp)) =
  92.       if pred x 
  93.           then Cons(x, delay(fn()=> filter pred (pull xp)))
  94.       else filter pred (pull xp);
  95.  
  96.   (*idea thanks to C. Reade, see Appendix 3 of his book *)
  97.   fun cycle seqfn =
  98.       let val knot = ref Nil
  99.       in  knot := seqfn (fn()=> !knot);  !knot  end;
  100.   end;
  101.  
  102.  
  103. (*** Ring Buffers, or Doubly Linked Lists ***)
  104.  
  105. signature RINGBUF = 
  106.   sig
  107.   type 'a T
  108.   exception E
  109.   val empty: unit -> '_a T
  110.   val null: 'a T -> bool
  111.   val label: 'a T -> 'a
  112.   val moveleft: 'a T -> unit
  113.   val moveright: 'a T -> unit
  114.   val insert: '_a T * '_a -> unit
  115.   val delete: 'a T -> 'a
  116.   end;
  117.  
  118.  
  119. structure Ringbuf : RINGBUF =
  120.   struct
  121.   datatype 'a buf = Empty
  122.           | Node of 'a buf ref * 'a * 'a buf ref;
  123.   datatype 'a T = Ptr of 'a buf ref;
  124.  
  125.   exception E;
  126.  
  127.   fun left (Node(lp,_,_)) = lp
  128.     | left Empty = raise E;
  129.  
  130.   fun right (Node(_,_,rp)) = rp
  131.     | right Empty = raise E;
  132.  
  133.   fun empty() = Ptr(ref Empty);
  134.  
  135.   fun null (Ptr p) = case !p of Empty => true
  136.                   | Node(_,x,_) => false;
  137.  
  138.   fun label (Ptr p) = case !p of Empty => raise E
  139.                    | Node(_,x,_) => x;
  140.  
  141.   fun moveleft (Ptr p) = (p := !(left(!p)));
  142.  
  143.   fun moveright (Ptr p) = (p := !(right(!p)));
  144.  
  145.   (*Insert to left of the window, which is unchanged unless empty. *)
  146.   fun insert (Ptr p, x) =
  147.       case !p of
  148.       Empty => 
  149.           let val lp = ref Empty
  150.           and rp = ref Empty
  151.           val new = Node(lp,x,rp)
  152.           in  lp := new;  rp := new;  p := new  end
  153.     | Node(lp,_,_) =>
  154.           let val new = Node(ref(!lp), x, ref(!p))
  155.           in  right(!lp) := new;  lp := new  end;
  156.  
  157.   (*Delete the current node, raising E if there is none. *)
  158.   fun delete (Ptr p) =
  159.       case !p of
  160.       Empty => raise E
  161.     | Node(lp,x,rp) =>
  162.          (if left(!lp) = lp then p := Empty
  163.           else (right(!lp) := !rp;  left (!rp) := !lp;
  164.             p := !rp);
  165.               x)
  166.   end;
  167.  
  168.  
  169. (**** V-arrays; see A. Aasa, S. Holmstr\"om, C. Nilsson (1988) ***)
  170.  
  171. nonfix sub;  (*required for Standard ML of New Jersey*)
  172.  
  173. signature VARRAY = 
  174.   sig
  175.   type 'a T
  176.   exception E
  177.   val array: int * '_a -> '_a T
  178.   val reroot: 'a T -> 'a T
  179.   val sub: 'a T * int -> 'a
  180.   val just_update: '_a T * int * '_a -> '_a T
  181.   val update: '_a T * int * '_a -> '_a T
  182.   end;
  183.  
  184.  
  185. structure Varray : VARRAY =
  186.   struct
  187.   datatype 'a T = Modif of {limit: int, 
  188.                 index: int ref,
  189.                 elem: 'a ref, 
  190.                 next: 'a T ref}
  191.         | Vector of 'a Array.array;
  192.  
  193.   exception E;
  194.  
  195.   (*create a new array containing x in locations 0 to n-1. *)
  196.   fun array (n,x) = 
  197.     if n <= 0  then  raise E
  198.     else  Modif{limit=n, index=ref 0, elem=ref x, 
  199.             next=ref(Vector(Array.array(n,x)))};
  200.  
  201.   fun reroot (va as Modif{index, elem, next,...}) =
  202.       case !next of
  203.      Vector _ => va  (*have reached root*)
  204.        | Modif _ => 
  205.        let val Modif{index=bindex,elem=belem,next=bnext,...} =
  206.              reroot (!next)
  207.            val Vector vec = !bnext
  208.        in  bindex := !index;  
  209.            belem := Array.sub(vec, !index);
  210.            Array.update(vec, !index, !elem);
  211.            next := !bnext;
  212.            bnext := va;
  213.            va
  214.        end;
  215.  
  216.   fun sub (Modif{index,elem,next,...}, i) =
  217.        case !next of
  218.       Vector vec => Array.sub(vec,i)
  219.     | Modif _ =>    if  !index=i  then  !elem  
  220.                       else  sub(!next,i);
  221.  
  222.   (*plain update, no rerooting*)
  223.   fun just_update(va as Modif{limit,...}, i, x) = 
  224.     if  0<=i andalso i<limit  
  225.     then Modif{limit=limit, index= ref i, 
  226.                    elem=ref x, next=ref va}
  227.     else raise E;
  228.  
  229.   (*update and reroot*)
  230.   fun update(va,i,x) = reroot(just_update(va,i,x));
  231.  
  232.   end;
  233.  
  234.  
  235. (******** SHORT DEMONSTRATIONS ********)
  236.  
  237. (** Sequences ***)
  238. structure Seq = ImpSeqFUN();
  239.  
  240. fun pairs (xq,yq) = 
  241.       Seq.cons((Seq.hd xq, Seq.hd yq), 
  242.                 fn()=>pairs(Seq.tl xq, Seq.tl yq));
  243.  
  244. fun add (xq,yq): int Seq.T = Seq.map op+ (pairs(xq,yq));
  245.  
  246. val fib = Seq.cycle(fn fibf =>
  247.     Seq.cons(1, fn()=> 
  248.          Seq.cons(1, fn()=> 
  249.               add(fibf(), Seq.tl(fibf())))));
  250.  
  251. (*if it returns quickly, sharing works;
  252.   if not shared, computation time is EXPONENTIAL in length of sequence *)
  253. Seq.take(40,fib);
  254.  
  255.  
  256.