68 lines · 1.8 KB · Standard ML
RawDownload
(* Example: implementing dynamically sized, functional arrays             using first-class modules *) (* the  signature  "Array" specifies a structure implementing fixed-size arrays.*) signature  Array  =  sig  type 'a array;       val init:'a  ->  ('a array);       val sub: ('a array)  ->  int  ->  'a;       val update: ('a array)  ->  int  ->  'a  ->  ('a array)  end; (* the structure "ArrayZero" implements arrays of size 2^0 = 1*) structure  ArrayZero =    struct         type 'a array = 'a;         fun init x = x;         fun sub a i = a         fun update a i x = x    end;  (* The  functor  "ArraySucc"  maps  an  implementation     of arrays of size 2^n  to an implementation of arrays of size 2^(n+1)*)functor ArraySucc (A:Array) =      struct             type 'a array  =  ('a A.array)  *  ('a A.array);                         fun init x =  (A.init  x, A.init  x)             fun sub (even,odd) i =                   if  (i mod  2) = 0                   then A.sub  even  (i div  2)                   else A.sub  odd  (i div 2);             fun update  (even,odd) i x =    		   if  (i mod  2) = 0		   then (A.update even (i div  2)  x, odd)		   else (even, A.update  odd (i div 2)  x)      end; (* The  Core function  "mkArray n" (n >=0)  returns an package implementating   arrays of size 2^n.*) fun  mkArray 0 = [structure  ArrayZero  as  Array]        (* base case *)  |  mkArray n = let structure A as Array = mkArray (n-1) (* inductive step *)		 in                     [structure  ArraySucc(A)  as  Array]                 end;  (* tests *)(* create a package implementing arrays of size 2^10 = 1024 and unpack it *)structure A as Array = mkArray 10; val a = A.init "yes"; (* an array of 1024 strings *)val test1 = A.sub a 864 = "yes";val test2 = A.sub (A.update a 864 "no") 864 = "no";