caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: oleg@pobox.com
To: Alain.Frisch@inria.fr
Cc: caml-list@inria.fr
Cc: ccshan@cs.rutgers.edu
Subject: Re: [Caml-list] Eliminating array bounds check
Date: Tue,  5 Sep 2006 22:03:40 -0700 (PDT)	[thread overview]
Message-ID: <20060906050340.7D87BABF9@Adric.metnet.fnmoc.navy.mil> (raw)
In-Reply-To: <44FBD432.8030602@inria.fr>


Hello!

> module GenT(X:sig end) : sig type t val v : t end =
>   struct type t = int let v = 1 end
> ;;
> let module M1 = GenT(struct end) in
> let module M2 = GenT(struct end) in
> M1.v = M2.v
> ;;

That is very nice! Thank you.

> (Ok, you must then trust the client not to apply GenT with
> named structures.)
I can hide this code in a trusted kernel: I merely need to be able to
generate unique types. Frankly, what bsearch code really needed is
local generative modules -- something like (in SML notation)

val test = let local structure A = Kernel(val a = ...)
	       open A in ... end in ...

According to my reading of the Definition of the Standard ML, this is
allowed. Alas, neither SML/NJ nor Poly/ML support this pattern.


> Unfortunaly, you cannot make a polymorphic functor such as:
>   module GenT(A : sig val a : 'a array end) ...

But the following close approximation works:

module GenT(A : sig type e val a : e array end) 
  : sig
    type barray
    type bindex
    type bindexL
    type bindexH
    val init_indexL  : bindexL
    val init_indexH  : bindexH
    val the_arr : barray
    val cmp : bindexL -> bindexH -> (bindex * bindex) option
    val get : barray -> bindex -> A.e
end = struct
    type barray = A.e array
    type bindex = int
    type bindexL = int
    type bindexH = int
    let the_arr = A.a
    let init_indexL = 0
    let init_indexH = Array.length A.a - 1
    let cmp i j = if i <= j then Some (i,j) else None
    let get = Array.get
end;;

let test1 = let module X = GenT(struct type e = int let a = [|1;2|] end) in
	    match X.cmp X.init_indexL X.init_indexH with
	     Some (i,j) -> X.get X.the_arr j
;;

let test2 = let a = [|1;2|]  in
	    let module X = GenT(struct type e = int let a = a end) in
	    let module Y = GenT(struct type e = int let a = a end) in
	    match X.cmp X.init_indexL X.init_indexH with
	     Some (i,j) -> X.get Y.the_arr j
;;
(* expected error:
  This expression has type Y.barray but is here used with type X.barray
*)

(* But this is OK *)
let test3 = let module N = struct type e = int let a = [|1;2|] end in
	    let module X = GenT(N) in
	    let module Y = GenT(N) in
	    match X.cmp X.init_indexL X.init_indexH with
	     Some (i,j) -> X.get Y.the_arr j;;


For formalization, the higher-rank types seem better (System F is
easier to formalize than lambda-calculus plus the module system). For
real work, the module system is obviously nicer. Thank you for the
suggestions!


> As a work-around, you can take only the length of the array as an argument:
>   module TrustedKernel(L: sig val len: int end) : sig
Hmm, that means that modular arithmetics and implicit configurations
described in
	http://www.eecs.harvard.edu/~ccshan/prepose/prepose.pdf
	http://www.eecs.harvard.edu/~ccshan/prepose/talk.ps.gz

are immediately implementable in OCaml. That is very neat.

module ModularNum (M : sig val modulus : int end) 
  : sig
     type t
     val of_int : int -> t
     val to_int : t -> int
     val ( +$ )  : t -> t -> t
     val ( -$ )  : t -> t -> t
     val ( *$ )  : t -> t -> t
     val normalize : int -> t
   end = struct
     type t = int
     let normalize a = a mod M.modulus
     let of_int x = normalize x
     let to_int x = x
     let ( +$ ) x y = normalize (x + y)
     let ( -$ ) x y = normalize (x - y)
     let ( *$ ) x y = normalize (x * y)
end;;

(* (3*3 + 5*5) modulo 4 *)
let test3 = let module XXX = struct
          module M = ModularNum(struct let modulus = 4 end)
	  open M
	  let a = of_int 3 and b = of_int 5
	  let v = a *$ a +$  b *$ b
	  let result = to_int v
	 end in XXX.result
;;
(* The modulus is implicit, just as desired. *)
(* It is clear that with a bit of camlp4 sugar, the boilerplate 
   can be removed and we can write something like
   let test3 = with_modulus 4 (let a = of_int 3 and b = of_int 5 in
                               a *$ a +$  b *$ b)
*)


(* testing non-interference: can't mix computations with different
   moduli
The error message,
    This expression has type M.t but is here used with type M.t
could be more helpful, though...
*)

(* A computation polymorphic over the modulus *)
module Foo(M : sig val modulus : int end) = struct
  module M = ModularNum(M)
  open M
  let a = of_int 1000
  let v = a *$ a *$ of_int 5 +$  of_int 2000
  let result = to_int v
end
;;

(* Run the Foo computation over the series of moduli *)
let test4 = List.map
    (fun m -> let module M = Foo(struct let modulus = m end) in M.result)
    [1;2;3;4;5;6;7;8;9]
;;


  parent reply	other threads:[~2006-09-06  5:07 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-09-04  1:00 oleg
2006-09-04  7:22 ` [Caml-list] " Alain Frisch
2006-09-04  7:42   ` Alain Frisch
2006-09-06  5:03   ` oleg [this message]
2006-09-06  5:15     ` Jonathan Roewen
2006-09-07  9:48       ` oleg
2006-09-04  9:43 ` skaller

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20060906050340.7D87BABF9@Adric.metnet.fnmoc.navy.mil \
    --to=oleg@pobox.com \
    --cc=Alain.Frisch@inria.fr \
    --cc=caml-list@inria.fr \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).