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