packages feed

alms-0.4.9: 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    : all 'a. int -> 'a -> ex 't. ('a, 't) array * 't writecap
  val build  : all 'a. int -> (int -> 'a) ->
                 ex 't. ('a, 't) array * 't writecap
  val split  : all 't 'c. ('t, 'c) readcap ->
                 ('t, 'c/2) readcap * ('t, 'c/2) readcap
  val join   : all 't 'c.  ('t, 'c/2) readcap * ('t, 'c/2) readcap ->
                 ('t, 'c) readcap
  val get    : all 'a 't 'c. ('a, 't) array -> int -> ('t, 'c) readcap ->
                 'a * ('t, 'c) readcap
  val set    : all 'a 't. ('a, 't) array -> int -> 'a ->
                 't writecap -> 't writecap
  val size   : all 'a 't. ('a, 't) array -> int
end

module AArray : sig
  include AARRAY_PRIM

  val par    : all 't 'c `r1 `r2.
                 (all 'd. ('t, 'd) readcap -> `r1 * ('t, 'd) readcap) ->
                 (all 'd. ('t, 'd) readcap -> `r2 * ('t, 'd) readcap) ->
                 ('t, 'c) readcap ->
                 `r1 * `r2 * ('t, 'c) readcap
  val fold   : all 'a 't 'c `r.
                 ('a -> `r -> `r) -> `r -> ('a, 't) array -[r]>
                 ('t, 'c) readcap -[r]>
                 `r * ('t, 'c) readcap
  val map    : all 'a 't 'c 'b.
                 ('a -> 'b) -> ('a, 't) array -> ('t, 'c) readcap ->
                 (ex 's. ('b, 's) array * 's writecap) * ('t, 'c) readcap
  val putArray
             : all '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['a] (size: int) (x : 'a) =
      Pack[ex 't. ('a, 't) array * unit]
          (unit, A.new['a] size x, ())

    let build['a] (size: int) (builder : int -> 'a) =
      Pack[ex 't. ('a, 't) array * unit]
          (unit, A.build['a] size builder, ())

    let split['t,'c] () = ((), ())

    let join['t,'c] (_: unit * unit) = ()

    let get['a,'t,'c] (arr: ('a, 't) array) (ix: int) () =
      (A.get arr ix, ())

    let set['a,'t] (arr: ('a, 't) array) (ix: int) (new: 'a) () =
      A.set arr ix new

    let size['a,'t] (arr: ('a, 't) array) =
      A.size arr
  end : AARRAY_PRIM

  let par ['t,'c,`r1,`r2]
          (left:  all 'd. ('t, 'd) readcap -> `r1 * ('t, 'd) readcap)
          (right: all '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 (fun () -> left c1) in
    let (r2, c2) = right c2 in
    let (r1, c1) = Future.sync future in
      (r1, r2, join (c1, c2))

  let fold ['a,'t,'c,`r]
           (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 ['a,'t,'c,'b]
          (f: 'a -> 'b)
          (a: ('a, 't) array) (c: ('t, 'c) readcap)
          : (ex '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,'t,'c] (a: ('a, 't) array) (c: ('t, 'c) readcap) =
    putStr "[";
    let (_, c) =
      fold (fun (x: 'a) (comma: bool) ->
              (if comma then putStr "," else ());
              putStr (string_of x);
              true)
           false a c in
    putStrLn "]";
    c
end