alms-0.6.0: lib/libarraycap.alms
(*
An affine array library.
*)
#load "libarray"
module type AARRAY_PRIM = sig
type ('a, 't) array
type `a / `b
type 1
type 2
type ('t, 'c) readcap qualifier A
type 't writecap = ('t, 1) readcap
val new : ∀ 'a. int → 'a → ∃ 't. ('a, 't) array * 't writecap
val build : ∀ 'a. int → (int → 'a) →
∃ 't. ('a, 't) array * 't writecap
val split : ∀ 't 'c. ('t, 'c) readcap →
('t, 'c/2) readcap * ('t, 'c/2) readcap
val join : ∀ 't 'c. ('t, 'c/2) readcap * ('t, 'c/2) readcap →
('t, 'c) readcap
val get : ∀ 'a 't 'c. ('a, 't) array → int → ('t, 'c) readcap →
'a * ('t, 'c) readcap
val set : ∀ 'a 't. ('a, 't) array → int → 'a →
't writecap → 't writecap
val size : ∀ 'a 't. ('a, 't) array → int
end
module AArray : sig
include AARRAY_PRIM
val par : ∀ 't 'c `r1 `r2.
(∀ 'd. ('t, 'd) readcap → `r1 * ('t, 'd) readcap) →
(∀ 'd. ('t, 'd) readcap → `r2 * ('t, 'd) readcap) →
('t, 'c) readcap →
`r1 * `r2 * ('t, 'c) readcap
val fold : ∀ 'a 't 'c `r.
('a → `r → `r) → `r → ('a, 't) array -r>
('t, 'c) readcap -r>
`r * ('t, 'c) readcap
val map : ∀ 'a 't 'c 'b.
('a → 'b) → ('a, 't) array → ('t, 'c) readcap →
(∃ 's. ('b, 's) array * 's writecap) * ('t, 'c) readcap
val putArray
: ∀ 'a 't 'c. ('a, 't) array → ('t, 'c) readcap →
('t, 'c) readcap
end = struct
module A = Array
open struct
type ('a, 't) array = 'a A.array
type `a / `b
type 1
type 2
type ('t, 'c) readcap = unit
type 't writecap = ('t, 1) readcap
let new size x : ∃ 't. ('a, 't) array * 't writecap =
(A.new size x, ())
let build size builder : ∃ 't. ('a, 't) array * 't writecap =
(A.build size builder, ())
let split () = ((), ())
let join (_: unit * unit) = ()
let get (arr: ('a, 't) array) (ix: int) () =
(A.get arr ix, ())
let set (arr: ('a, 't) array) (ix: int) (new: 'a) () =
A.set arr ix new
let size (arr: ('a, 't) array) =
A.size arr
end : AARRAY_PRIM
let par (left: ∀ 'd. ('t, 'd) readcap → `r1 * ('t, 'd) readcap)
(right: ∀ 'd. ('t, 'd) readcap → `r2 * ('t, 'd) readcap)
(c: ('t, 'c) readcap)
: `r1 * `r2 * ('t, 'c) readcap =
let (c1, c2) = split c in
let future = Future.new (λ () → left c1) in
let (r2, c2) = right c2 in
let (r1, c1) = Future.sync future in
(r1, r2, join (c1, c2))
let fold (f: 'a → `r → `r) (z: `r)
(a: ('a, 't) array) (c: ('t, 'c) readcap) =
let rec loop (i: int) (z: `r) (c: ('t, 'c) readcap)
: `r * ('t, 'c) readcap =
if i < size a
then let (elt, c) = get a i c in
loop (i + 1) (f elt z) c
else (z, c)
in loop 0 z c
let map (f: 'a → 'b)
(a: ('a, 't) array) (c: ('t, 'c) readcap)
: (∃ 's. ('b, 's) array * 's writecap) * ('t, 'c) readcap =
let holder = ref (Some c) in
let builder (ix : int) = match holder <- None with
| None → failwith "can't happen"
| Some c →
let (x, c) = get a ix c in
holder <- Some c;
f x in
let res = build (size a) builder in
match holder <- None with
| None → failwith "can't happen"
| Some c → (res, c)
let putArray (a: ('a, 't) array) (c: ('t, 'c) readcap) =
putStr "[";
let (_, c) =
fold (λ (x: 'a) (comma: bool) →
(if comma then putStr "," else ());
putStr (string_of x);
true)
false a c in
putStrLn "]";
c
end