caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
From: Alain Frisch <Alain.Frisch@ens.fr>
To: Ross Duncan <ross.duncan@comlab.ox.ac.uk>
Cc: Caml list <caml-list@pauillac.inria.fr>
Subject: Re: [Caml-list] Conditional Modules
Date: Thu, 5 Aug 2004 14:34:56 +0200 (MET DST)	[thread overview]
Message-ID: <Pine.SOL.4.44.0408051417220.8762-100000@clipper.ens.fr> (raw)
In-Reply-To: <D3659702-E6D1-11D8-97DB-000A95C61840@comlab.ox.ac.uk>

On Thu, 5 Aug 2004, Ross Duncan wrote:

> So I guess my request for help should now become a feature request for
> the language!  Is this at all compatible with static typing?

Yes, it is. One issue is to specify the type of the result; one would like
to compute the least upper bound of the two module types. The
simple-minded patch below chooses a simpler method: it takes the type of
the first branch as the type for the result (the second branch must be
compatible with this type).

But there is no reason to stop with this if-then-else construction; one
could for instance import the match and the let-in construction from the
core language to the module language. A nice solution would be to make the
core language/type system and the module language/type system mutually
recursive. One simple solution has been proposed in:

Claudio V. Russo. First-Class Structures for Standard ML.
http://www.dcs.ed.ac.uk/home/cvr/

One would have a "pack" operation that takes a module value and turns
it into a core value (packed module), an "unpack" operation that takes
a packed module and turns it into a module value (with a given module
type). The if-then-else could be encoded as:

module M = unpack (if e then pack M1 else pack M2 : S)

but you could also do:

let f b =
  let module M = unpack (if e then pack M1 else pack M2 : S) in
  ...

I implemented some time ago such a patch for OCaml (actually, there was
only the "let module M = unpack (...)" construction and not the unpack in
the module language): http://www.eleves.ens.fr/home/frisch/soft#patches


-- Alain


diff -Naur ocaml/bytecomp/translmod.ml ocaml_if/bytecomp/translmod.ml
--- ocaml/bytecomp/translmod.ml	2004-06-12 10:55:45.000000000 +0200
+++ ocaml_if/bytecomp/translmod.ml	2004-08-05 14:04:22.000000000 +0200
@@ -268,6 +268,10 @@
                 [transl_module ccarg None arg]))
   | Tmod_constraint(arg, mty, ccarg) ->
       transl_module (compose_coercions cc ccarg) rootpath arg
+  | Tmod_ifthenelse(e,y,n,c) ->
+      Lifthenelse(transl_exp e,
+		  transl_module cc rootpath y,
+		  transl_module (compose_coercions cc c) rootpath n)

 and transl_structure fields cc rootpath = function
     [] ->
diff -Naur ocaml/parsing/parser.mly ocaml_if/parsing/parser.mly
--- ocaml/parsing/parser.mly	2004-05-19 14:15:19.000000000 +0200
+++ ocaml_if/parsing/parser.mly	2004-08-05 14:06:28.000000000 +0200
@@ -420,6 +420,8 @@
       { unclosed "(" 2 ")" 4 }
   | LPAREN module_expr COLON module_type RPAREN
       { mkmod(Pmod_constraint($2, $4)) }
+  | IF expr THEN module_expr ELSE module_expr
+      { mkmod(Pmod_ifthenelse($2,$4,$6)) }
   | LPAREN module_expr COLON module_type error
       { unclosed "(" 1 ")" 5 }
   | LPAREN module_expr RPAREN
diff -Naur ocaml/parsing/parsetree.mli ocaml_if/parsing/parsetree.mli
--- ocaml/parsing/parsetree.mli	2003-11-25 09:46:45.000000000 +0100
+++ ocaml_if/parsing/parsetree.mli	2004-08-05 13:51:26.000000000 +0200
@@ -236,6 +236,7 @@
   | Pmod_functor of string * module_type * module_expr
   | Pmod_apply of module_expr * module_expr
   | Pmod_constraint of module_expr * module_type
+  | Pmod_ifthenelse of expression * module_expr * module_expr

 and structure = structure_item list

diff -Naur ocaml/parsing/printast.ml ocaml_if/parsing/printast.ml
--- ocaml/parsing/printast.ml	2003-11-25 09:46:45.000000000 +0100
+++ ocaml_if/parsing/printast.ml	2004-08-05 13:52:31.000000000 +0200
@@ -545,6 +545,11 @@
       line i ppf "Pmod_constraint\n";
       module_expr i ppf me;
       module_type i ppf mt;
+  | Pmod_ifthenelse (e,y,n) ->
+      line i ppf "Pmod_ifthenelse\n";
+      expression i ppf e;
+      module_expr i ppf y;
+      module_expr i ppf n

 and structure i ppf x = list i structure_item ppf x

diff -Naur ocaml/typing/typedtree.ml ocaml_if/typing/typedtree.ml
--- ocaml/typing/typedtree.ml	2003-11-25 10:20:43.000000000 +0100
+++ ocaml_if/typing/typedtree.ml	2004-08-05 14:01:11.000000000 +0200
@@ -126,6 +126,7 @@
   | Tmod_functor of Ident.t * module_type * module_expr
   | Tmod_apply of module_expr * module_expr * module_coercion
   | Tmod_constraint of module_expr * module_type * module_coercion
+  | Tmod_ifthenelse of expression * module_expr * module_expr * module_coercion

 and structure = structure_item list

diff -Naur ocaml/typing/typedtree.mli ocaml_if/typing/typedtree.mli
--- ocaml/typing/typedtree.mli	2003-11-25 10:20:43.000000000 +0100
+++ ocaml_if/typing/typedtree.mli	2004-08-05 14:01:10.000000000 +0200
@@ -127,6 +127,7 @@
   | Tmod_functor of Ident.t * module_type * module_expr
   | Tmod_apply of module_expr * module_expr * module_coercion
   | Tmod_constraint of module_expr * module_type * module_coercion
+  | Tmod_ifthenelse of expression * module_expr * module_expr * module_coercion

 and structure = structure_item list

diff -Naur ocaml/typing/typemod.ml ocaml_if/typing/typemod.ml
--- ocaml/typing/typemod.ml	2004-06-13 14:48:01.000000000 +0200
+++ ocaml_if/typing/typemod.ml	2004-08-05 14:00:17.000000000 +0200
@@ -514,6 +514,20 @@
            mod_type = mty;
            mod_env = env;
            mod_loc = smod.pmod_loc }
+  | Pmod_ifthenelse(se,sy,sn) ->
+      let e = Typecore.type_expression env se in
+      let y = type_module anchor env sy in
+      let mty = y.mod_type in
+      let n = type_module anchor env sn in
+      let coercion =
+        try
+          Includemod.modtypes env n.mod_type mty
+        with Includemod.Error msg ->
+          raise(Error(sn.pmod_loc, Not_included msg)) in
+      rm { mod_desc = Tmod_ifthenelse(e,y,n,coercion);
+	   mod_type = mty;
+	   mod_env = env;
+	   mod_loc = smod.pmod_loc }

 and type_structure anchor env sstr =
   let type_names = ref StringSet.empty

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners


  reply	other threads:[~2004-08-05 12:35 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-08-04 14:58 Ross Duncan
2004-08-04 16:02 ` Richard Jones
2004-08-04 16:29   ` Michel Mauny
2004-08-04 16:45   ` John Prevost
2004-08-04 17:22     ` Shivkumar Chandrasekaran
2004-08-05 11:23     ` Ross Duncan
2004-08-05 12:34       ` Alain Frisch [this message]
2004-08-05 15:10       ` Jean-Baptiste Rouquier
2004-08-05 15:54         ` Christophe Raffalli
2004-08-06  7:53           ` Alain Frisch
2004-08-04 17:23 ` henri dubois-ferriere
2004-08-04 17:24 ` james woodyatt
2004-08-04 18:01   ` John Prevost

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=Pine.SOL.4.44.0408051417220.8762-100000@clipper.ens.fr \
    --to=alain.frisch@ens.fr \
    --cc=caml-list@pauillac.inria.fr \
    --cc=ross.duncan@comlab.ox.ac.uk \
    /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).