From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by walapai.inria.fr (8.13.6/8.13.6) with ESMTP id pA313Hd5003088 for ; Thu, 3 Nov 2011 02:03:17 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AloBAHDnsU7RVaE2kGdsb2JhbABEogMBh2wIIgEBAQEJCQ0HFAQhgXIBAQEDARICLAEbHQEDAQsGBQsGAwECAS4hAQERAQUBFAgGEyKHYAiXcQqLVIJghV49iHACBQqJBgSIB4wNijuCfj2EDg X-IronPort-AV: E=Sophos;i="4.69,446,1315173600"; d="scan'208";a="116434796" Received: from mail-fx0-f54.google.com ([209.85.161.54]) by mail4-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 03 Nov 2011 02:03:11 +0100 Received: by faar19 with SMTP id r19so1959448faa.27 for ; Wed, 02 Nov 2011 18:03:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=zAbWiuQJ4OAScCW3ma4qSPC1MrvLuFdPOcGBJ3i6muQ=; b=FRpTgsZHMRgGZzdsW3COCUs/hezTfRMZULCfnaCFlMChjKMcxQX+UqT/3EYvzb58z4 wQ/wyvLqynGwiJ7E+Dditlfuzkm+grxvhgfHXr2mPwtYGY4YL1APyXwfpmm02EKWcfL8 JYHhYzCudGOTx4XoBVxedcshXlqjloB7O3Wyw= MIME-Version: 1.0 Received: by 10.223.88.150 with SMTP id a22mr8639750fam.1.1320282191291; Wed, 02 Nov 2011 18:03:11 -0700 (PDT) Received: by 10.223.6.210 with HTTP; Wed, 2 Nov 2011 18:03:11 -0700 (PDT) In-Reply-To: References: <4EB1A5DB.8070405@gmail.com> Date: Wed, 2 Nov 2011 19:03:11 -0600 Message-ID: From: Anthony Tavener To: Gabriel Scherer Cc: caml-list@inria.fr Content-Type: multipart/alternative; boundary=0015175cae9203e5c904b0ca2730 Subject: Re: [Caml-list] Nested module exposing type from parent? --0015175cae9203e5c904b0ca2730 Content-Type: text/plain; charset=ISO-8859-1 I had tried this before, because the first thing I did was run into the cyclic type due to types being implicitly recursive. And I found that Janestreet article... I'm sure I felt I had the answer then. But it didn't work for my needs, because I wanted access to the record fields when opening the sub-module. This is where Vincent's suggestion of using 'include' made the difference. Thank-you though! On Wed, Nov 2, 2011 at 5:01 PM, Gabriel Scherer wrote: > I see that you solved your problem in a way you find satisfying, but I > would like to point out that the reason why your original code didn't > work isn't exactly what you seem to think. > > When you define a submodule, the types defined before in the parent > modules are perfectly accessible and can be referred, just as you > would do when referring to types defined at the toplevel. You need not > qualify the type with the outer module name (Vec.t in your example), > as you are still *inside* this parent module. > > module Vec = struct > type t = int > module Type = struct > type u = t > end > end > > (1 : Vec.Type.u);; > > The problem in your case is that you wish to give the same name to the > type in Vec and in Vec.Type. This would lead to the following: > ... module Type = struct type t = t end ... > > But this is ill-defined : it is a recursive type defined as being > itself. The problem is that the OCaml syntax for type declarations > always consider them recursive (for values you have "let" and "let > rec", for types you have "type" which behaves like "type rec" with no > opt-out way possible). This is a flaw of the OCaml syntax which is > relatively well-known, see eg. http://ocaml.janestreet.com/?q=node/25 > > A workaround is to define your inner type "t" in two steps, using an > different intermediate name to break the cycle: > > module Vec = struct > type t = int > module Type = struct > type u = t > type t = u > end > end > > (1 : Vec.Type.t);; > > > On Wed, Nov 2, 2011 at 10:14 PM, Anthony Tavener > wrote: > > Oops, I didn't do a group-reply... so in case anyone is interested in > what I > > ended up with: > > > > ---------- Forwarded message ---------- > > From: Anthony Tavener > > Date: Wed, Nov 2, 2011 at 2:50 PM > > Subject: Re: [Caml-list] Nested module exposing type from parent? > > To: Vincent Aravantinos > > > > > > Actually, better than I initially thought... > > I keep this as I have them defined already, except as you said: include > > instead of open. > > module Vec = struct > > module Type = struct > > type t = { x: int; y: int } > > end > > include Type > > let make x y = {x;y} > > let add a b = {x=a.x+b.x; y=a.y+b.y} > > end > > Before, I had instead of the include: > > type t = Type.t > > open Type > > Which worked, but then the type used everywhere was Vec.Type.t > > Thanks again! Simple and effective, and I was looking in all the wrong > > places. :) > > On Wed, Nov 2, 2011 at 2:36 PM, Anthony Tavener < > anthony.tavener@gmail.com> > > wrote: > >> > >> Thank-you Vincent! > >> Though this requires a home for the "source type" module, at least the > >> types come out right in the end. Thanks! > >> And this led me to read specifically about include to understand what it > >> really does. :) > >> > >> On Wed, Nov 2, 2011 at 2:19 PM, Vincent Aravantinos > >> wrote: > >>> > >>> Using "include" instead of "open" would work, ie. turning your example > >>> into: > >>> > >>> module Vec_main = struct > >>> type t = { x: int; y: int } > >>> let make x y = {x;y} > >>> let add a b = {x=a.x+b.x; y=a.y+b.y} > >>> end > >>> > >>> module Vec = struct > >>> include Vec_main > >>> module Type = struct > >>> include Vec_main > >>> ... > >>> end > >>> end > >>> > >>> Then: > >>> # let n = Vec.make 2 5;; > >>> val n : Vec.t = {Vec.x = 2; Vec.y = 5} > >>> # open Vec.Type;; > >>> # let m = {x=1;y=2};; > >>> val m : Vec.Type.t = {x = 1; y = 2} > >>> # Vec.add m n;; > >>> - : Vec.t = {Vec.x = 3; Vec.y = 7} > >>> > >>> Cheers > >>> > >>> -- > >>> Vincent Aravantinos - Postdoctoral Fellow, Concordia University, > Hardware > >>> Verification Group > >>> > >>> On 11/02/2011 03:41 PM, Anthony Tavener wrote: > >>> > >>> I've been struggling with this occasionally... > >>> I'm using nested modules to "open" access to select features of a > module. > >>> My problem is I can't find a way to *expose* types in the parent module > >>> through such nested modules. > >>> A simplified example of what I'm looking at: > >>> module Vec = struct > >>> type t = { x: int; y: int } > >>> let make x y = {x;y} > >>> let add a b = {x=a.x+b.x; y=a.y+b.y} > >>> module Type = > >>> (* something which has type t = Vec.t, > >>> * with exposed structure when "open"ed. > >>> * Also note that Vec is not really an > >>> * explicit module like this; instead it > >>> * is implemented in vec.ml *) > >>> end > >>> Example usage... > >>> let n = Vec.make 2 5 > >>> open Vec.Type > >>> let m = {x=1;y=2} > >>> Vec.add m n > >>> > >>> To date, I've defined the type in the Type submodule, which is then > used > >>> by the parent module. The unsatisfactory quality of this is that > Vec.Type.t > >>> is the "true" type. Ideally the concrete type would live at Vec.t, with > >>> "open Vec.Type" bringing the fields of the type into scope. > >>> As background, here are examples of opening different features of the > Vec > >>> module: > >>> let c = Vec.add a b > >>> open Vec.Prefixed > >>> let c = vadd a b > >>> open Vec.Ops > >>> let c = a +| b > >>> open Vec.Type > >>> let c = Vec.add a {x;y;z=0.} > >>> Apologies if this is really beginner-list material. It's minor, but has > >>> been bugging me. > >>> Thank-you for looking, > >>> Tony > >>> > >> > > > > > > > --0015175cae9203e5c904b0ca2730 Content-Type: text/html; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable I had tried this before, because the first thing I did was run into the cyc= lic type due to types being implicitly recursive. And I found that Janestre= et article... I'm sure I felt I had the answer then. But it didn't = work for my needs, because I wanted access to the record fields when openin= g the sub-module. This is where Vincent's suggestion of using 'incl= ude' made the difference. Thank-you though!


On Wed, Nov 2, 2011 at 5:01 P= M, Gabriel Scherer <gabriel.scherer@gmail.com> wrote:
I see that you solved your problem in a way you find satisfying, but I
would like to point out that the reason why your original code didn't work isn't exactly what you seem to think.

When you define a submodule, the types defined before in the parent
modules are perfectly accessible and can be referred, just as you
would do when referring to types defined at the toplevel. You need not
qualify the type with the outer module name (Vec.t in your example),
as you are still *inside* this parent module.

=A0module Vec =3D struct
=A0 =A0type t =3D int
=A0 =A0module Type =3D struct
=A0 =A0 =A0type u =3D t
=A0 =A0end
=A0end

=A0(1 : Vec.Type.u);;

The problem in your case is that you wish to give the same name to the
type in Vec and in Vec.Type. This would lead to the following:
=A0... module Type =3D struct type t =3D t end ...

But this is ill-defined : it is a recursive type defined as being
itself. The problem is that the OCaml syntax for type declarations
always consider them recursive (for values you have "let" and &qu= ot;let
rec", for types you have "type" which behaves like "typ= e rec" with no
opt-out way possible). This is a flaw of the OCaml syntax which is
relatively well-known, see eg. http://ocaml.janestreet.com/?q=3Dnode/25

A workaround is to define your inner type "t" in two steps, using= an
different intermediate name to break the cycle:

=A0module Vec =3D struct
=A0 =A0type t =3D int
=A0 =A0module Type =3D struct
=A0 =A0 =A0type u =3D t
=A0 =A0 =A0type t =3D u
=A0 =A0end
=A0end

=A0(1 : Vec.Type.t);;


On Wed, Nov 2, 2011 at 10:14 PM, Anthony Tavener
<anthony.tavener@gmail.com> wrote:
> Oops, I didn't do a group-reply... so in case anyone is interested= in what I
> ended up with:
>
> ---------- Forwarded message ----------
> From: Anthony Tavener <anthony.tavener@gmail.com>
> Date: Wed, Nov 2, 2011 at 2:50 PM
> Subject: Re: [Caml-list] Nested module exposing type from parent?
> To: Vincent Aravantinos <vincent.aravantinos@gmail.com>
>
>
> Actually, better than I initially thought...
> I keep this as I have them defined already, except as you said: includ= e
> instead of open.
> =A0 module Vec =3D struct
> =A0 =A0 module Type =3D struct
> =A0 =A0 =A0 type t =3D { x: int; y: int }
> =A0 =A0 end
> =A0 =A0 include Type
> =A0 =A0 let make x y =3D {x;y}
> =A0 =A0 let add a b =3D {x=3Da.x+b.x; y=3Da.y+b.y}
> =A0 end
> Before, I had instead of the include:
> =A0 type t =3D Type.t
> =A0 open Type
> Which worked, but then the type used everywhere was Vec.Type.t
> Thanks again! Simple and effective, and I was looking in all the wrong=
> places. :)
> On Wed, Nov 2, 2011 at 2:36 PM, Anthony Tavener <anthony.tavener@gmail.com>
> wrote:
>>
>> Thank-you Vincent!
>> Though this requires a home for the "source type" module= , at least the
>> types come out right in the end. Thanks!
>> And this led me to read specifically about include to understand w= hat it
>> really does. :)
>>
>> On Wed, Nov 2, 2011 at 2:19 PM, Vincent Aravantinos
>> <vincent.arava= ntinos@gmail.com> wrote:
>>>
>>> Using "include" instead of "open" would wo= rk, ie. turning your example
>>> into:
>>>
>>> module Vec_main =3D struct
>>> =A0 type t =3D { x: int; y: int }
>>> =A0 let make x y =3D {x;y}
>>> =A0 let add a b =3D {x=3Da.x+b.x; y=3Da.y+b.y}
>>> end
>>>
>>> module Vec =3D struct
>>> =A0 include Vec_main
>>> =A0 module Type =3D struct
>>> =A0=A0=A0 include Vec_main
>>> =A0=A0=A0 ...
>>> =A0 end
>>> end
>>>
>>> Then:
>>> # let n =3D Vec.make 2 5;;
>>> val n : Vec.t =3D {Vec.x =3D 2; Vec.y =3D 5}
>>> # open Vec.Type;;
>>> # let m =3D {x=3D1;y=3D2};;
>>> val m : Vec.Type.t =3D {x =3D 1; y =3D 2}
>>> # Vec.add m n;;
>>> - : Vec.t =3D {Vec.x =3D 3; Vec.y =3D 7}
>>>
>>> Cheers
>>>
>>> --
>>> Vincent Aravantinos - Postdoctoral Fellow, Concordia Universit= y, Hardware
>>> Verification Group
>>>
>>> On 11/02/2011 03:41 PM, Anthony Tavener wrote:
>>>
>>> I've been struggling with this occasionally...
>>> I'm using nested modules to "open" access to sel= ect features of a module.
>>> My problem is I can't find a way to *expose* types in the = parent module
>>> through such nested modules.
>>> A simplified example of what I'm looking at:
>>> =A0 module Vec =3D struct
>>> =A0 =A0 type t =3D { x: int; y: int }
>>> =A0 =A0 let make x y =3D {x;y}
>>> =A0 =A0 let add a b =3D {x=3Da.x+b.x; y=3Da.y+b.y}
>>> =A0 =A0 module Type =3D
>>> =A0 =A0 =A0 (* something which has type t =3D Vec.t,
>>> =A0 =A0 =A0 =A0* with exposed structure when "open"e= d.
>>> =A0 =A0 =A0 =A0* Also note that Vec is not really an
>>> =A0 =A0 =A0 =A0* explicit module like this; instead it
>>> =A0 =A0 =A0 =A0* is implemented in vec.ml *)
>>> =A0 end
>>> Example usage...
>>> =A0 let n =3D Vec.make 2 5
>>> =A0 open Vec.Type
>>> =A0 let m =3D {x=3D1;y=3D2}
>>> =A0 Vec.add m n
>>>
>>> To date, I've defined the type in the Type submodule, whic= h is then used
>>> by the parent module. The unsatisfactory quality of this is th= at Vec.Type.t
>>> is the "true" type. Ideally the concrete type would = live at Vec.t, with
>>> "open Vec.Type" bringing the fields of the type into= scope.
>>> As background, here are examples of opening different features= of the Vec
>>> module:
>>> =A0 let c =3D Vec.add a b
>>> =A0 open Vec.Prefixed
>>> =A0 let c =3D vadd a b
>>> =A0 open Vec.Ops
>>> =A0 let c =3D a +| b
>>> =A0 open Vec.Type
>>> =A0 let c =3D Vec.add a {x;y;z=3D0.}
>>> Apologies if this is really beginner-list material. It's m= inor, but has
>>> been bugging me.
>>> Thank-you for looking,
>>> =A0Tony
>>>
>>
>
>
>

--0015175cae9203e5c904b0ca2730--