caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Nested module exposing type from parent?
@ 2011-11-02 19:41 Anthony Tavener
  2011-11-02 20:19 ` Vincent Aravantinos
  2011-11-03  0:41 ` Martin Jambon
  0 siblings, 2 replies; 8+ messages in thread
From: Anthony Tavener @ 2011-11-02 19:41 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 1359 bytes --]

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

[-- Attachment #2: Type: text/html, Size: 2016 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] Nested module exposing type from parent?
  2011-11-02 19:41 [Caml-list] Nested module exposing type from parent? Anthony Tavener
@ 2011-11-02 20:19 ` Vincent Aravantinos
       [not found]   ` <CAN=ouMTApZjpU-CaZtdL4njXtmtRu++7fzJBJL3w3FRcHfjtSA@mail.gmail.com>
  2011-11-03  0:41 ` Martin Jambon
  1 sibling, 1 reply; 8+ messages in thread
From: Vincent Aravantinos @ 2011-11-02 20:19 UTC (permalink / raw)
  To: Anthony Tavener; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 2139 bytes --]

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 <http://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
>


[-- Attachment #2: Type: text/html, Size: 4077 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Fwd: [Caml-list] Nested module exposing type from parent?
       [not found]     ` <CAN=ouMS9rqqNR3KgCBnnjC_HcMrUnftVw643mkmhC_vrpXfv1A@mail.gmail.com>
@ 2011-11-02 21:14       ` Anthony Tavener
  2011-11-02 23:01         ` Gabriel Scherer
  0 siblings, 1 reply; 8+ messages in thread
From: Anthony Tavener @ 2011-11-02 21:14 UTC (permalink / raw)
  To: caml-list

[-- Attachment #1: Type: text/plain, Size: 3580 bytes --]

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: 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 <
> vincent.aravantinos@gmail.com> 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
>>
>>
>>
>

[-- Attachment #2: Type: text/html, Size: 6332 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] Nested module exposing type from parent?
  2011-11-02 21:14       ` Fwd: " Anthony Tavener
@ 2011-11-02 23:01         ` Gabriel Scherer
  2011-11-03  0:06           ` Vincent Aravantinos
  2011-11-03  1:03           ` Anthony Tavener
  0 siblings, 2 replies; 8+ messages in thread
From: Gabriel Scherer @ 2011-11-02 23:01 UTC (permalink / raw)
  To: Anthony Tavener; +Cc: caml-list

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
<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: 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
>> <vincent.aravantinos@gmail.com> 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
>>>
>>
>
>
>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] Nested module exposing type from parent?
  2011-11-02 23:01         ` Gabriel Scherer
@ 2011-11-03  0:06           ` Vincent Aravantinos
  2011-11-03  1:03           ` Anthony Tavener
  1 sibling, 0 replies; 8+ messages in thread
From: Vincent Aravantinos @ 2011-11-03  0:06 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: Anthony Tavener, caml-list

[-- Attachment #1: Type: text/plain, Size: 6383 bytes --]

Maybe I am wrong but I have the feeling that this is totally unrelated  
to Anthony's question?
Could you please explain in more details how it solves the problem?
I actually tried your solution on Anthony's code but it does not solve  
his problem (if I understood it well of course).

--
Vincent Aravantinos
PostDoctoral fellow, Concordia University, Hardware Verification Group
http://users.encs.concordia.ca/~vincent


Le 2 nov. 11 à 19:01, Gabriel Scherer a écrit :

> 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
> <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:  
>> 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
>>> <vincent.aravantinos@gmail.com> 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
>>>>
>>>
>>
>>
>>
>
>
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>


[-- Attachment #2: Type: text/html, Size: 26764 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] Nested module exposing type from parent?
  2011-11-02 19:41 [Caml-list] Nested module exposing type from parent? Anthony Tavener
  2011-11-02 20:19 ` Vincent Aravantinos
@ 2011-11-03  0:41 ` Martin Jambon
  2011-11-03  1:04   ` Anthony Tavener
  1 sibling, 1 reply; 8+ messages in thread
From: Martin Jambon @ 2011-11-03  0:41 UTC (permalink / raw)
  To: caml-list

On 11/02/2011 12: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 <http://vec.ml> *)
>   end
> 
> Example usage...
> 
>   let n = Vec.make 2 5
>   open Vec.Type
>   let m = {x=1;y=2}
>   Vec.add m n

I hope I understand the problem correctly.

In order for that code to work, you can do this:

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 = struct
    type t' = t = { x: int; y: int }
    type t = t' = { x: int; y: int }
    (* 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 <http://vec.ml> *)
  end
end


Or more simply:


module Vec = struct

  module Type = struct
    type t = { x: int; y: int }
    (* 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 <http://vec.ml> *)
  end

  type t = 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


Now you can open either Vec or Vec.Type and have direct access to the
record fields.


Martin

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] Nested module exposing type from parent?
  2011-11-02 23:01         ` Gabriel Scherer
  2011-11-03  0:06           ` Vincent Aravantinos
@ 2011-11-03  1:03           ` Anthony Tavener
  1 sibling, 0 replies; 8+ messages in thread
From: Anthony Tavener @ 2011-11-03  1:03 UTC (permalink / raw)
  To: Gabriel Scherer; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 5996 bytes --]

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
<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.
>
>  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
> <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: 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
> >> <vincent.aravantinos@gmail.com> 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
> >>>
> >>
> >
> >
> >
>

[-- Attachment #2: Type: text/html, Size: 8194 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [Caml-list] Nested module exposing type from parent?
  2011-11-03  0:41 ` Martin Jambon
@ 2011-11-03  1:04   ` Anthony Tavener
  0 siblings, 0 replies; 8+ messages in thread
From: Anthony Tavener @ 2011-11-03  1:04 UTC (permalink / raw)
  To: Martin Jambon; +Cc: caml-list

[-- Attachment #1: Type: text/plain, Size: 2655 bytes --]

Aha! That's more like what I was going for, Martin.

I didn't realize you could equate types in a chain like that, permitting
the definition of structure but also equality to another existing type.
That's good stuff.

This list, and OCaml, often amaze me... solutions keep getting better. :)


On Wed, Nov 2, 2011 at 6:41 PM, Martin Jambon <martin.jambon@ens-lyon.org>wrote:

> On 11/02/2011 12: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 <http://vec.ml> *)
> >   end
> >
> > Example usage...
> >
> >   let n = Vec.make 2 5
> >   open Vec.Type
> >   let m = {x=1;y=2}
> >   Vec.add m n
>
> I hope I understand the problem correctly.
>
> In order for that code to work, you can do this:
>
> 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 = struct
>    type t' = t = { x: int; y: int }
>    type t = t' = { x: int; y: int }
>     (* 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 <http://vec.ml> *)
>  end
> end
>
>
> Or more simply:
>
>
> module Vec = struct
>
>  module Type = struct
>     type t = { x: int; y: int }
>     (* 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 <http://vec.ml> *)
>  end
>
>  type t = 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
>
>
> Now you can open either Vec or Vec.Type and have direct access to the
> record fields.
>
>
> Martin
>
> --
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
>
>

[-- Attachment #2: Type: text/html, Size: 4144 bytes --]

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2011-11-03  1:04 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-02 19:41 [Caml-list] Nested module exposing type from parent? Anthony Tavener
2011-11-02 20:19 ` Vincent Aravantinos
     [not found]   ` <CAN=ouMTApZjpU-CaZtdL4njXtmtRu++7fzJBJL3w3FRcHfjtSA@mail.gmail.com>
     [not found]     ` <CAN=ouMS9rqqNR3KgCBnnjC_HcMrUnftVw643mkmhC_vrpXfv1A@mail.gmail.com>
2011-11-02 21:14       ` Fwd: " Anthony Tavener
2011-11-02 23:01         ` Gabriel Scherer
2011-11-03  0:06           ` Vincent Aravantinos
2011-11-03  1:03           ` Anthony Tavener
2011-11-03  0:41 ` Martin Jambon
2011-11-03  1:04   ` Anthony Tavener

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).