(* Author: Claudio Vittorio Russo, Department of Computer Science, University of Edinburgh, Scotland Copyright: 1998. All rights reserved. *) (* 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 implementing arrays of size 2^0. *) structure ArrayZero = struct type 'a array = 'a; val init = fn x => x; val sub = fn a => fn i => a; val update = fn a => fn i => fn x => x end; (* The functor ArraySucc mapping 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); val init = fn x => (A.init x, A.init x) val sub = fn (even,odd) => fn i => if (i mod 2) = 0 then A.sub even (i div 2) else A.sub odd (i div 2); val update = fn (even,odd) => fn i => fn 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 function mkArray: applying mkArray to an integer n (n >=0) returns an abstract implementation of arrays of size 2^n *) fun mkArray 0 = [structure ArrayZero as Array] | mkArray n = let structure A as Array = mkArray (n-1) in [structure ArraySucc(A) as Array] end ; fun two 0 = 1 | two n = 2 * two (n-1); val n = 10; val max = two n; fun iter f b 0 = b | iter f b n = f (iter f b (n-1)) n; structure A as Array = mkArray n; val a = A.init 0; (* test every entry is initialised to zero *) val test1 = if iter (fn l => fn n => l andalso (A.sub a n) = 0) true max then "OK" else "FAIL"; val a = iter (fn a => fn n => A.update a n n) a max; val l = iter (fn l => fn n => (A.sub a n)::l) [] max (* test every entry has been updated *) val test2 = if iter (fn l => fn n => l andalso (A.sub a n) = n) true max then "OK" else "FAIL";