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 pA2N2NNj031188 for ; Thu, 3 Nov 2011 00:02:23 +0100 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AloBAF7LsU5KfVK2kGdsb2JhbABEqW8IIgEBAQEJCQ0HFAQhgXIBAQEEEgIsARsdAQMMBgULBgMBAgEuIQEBEQEFARQIBhMIGodol2kKi1SCYIVYPYhwAgUKiQYElBSKO4J+PYNw X-IronPort-AV: E=Sophos;i="4.69,446,1315173600"; d="scan'208";a="116408627" Received: from mail-wy0-f182.google.com ([74.125.82.182]) by mail4-smtp-sop.national.inria.fr with ESMTP/TLS/RC4-SHA; 03 Nov 2011 00:02:18 +0100 Received: by wyg36 with SMTP id 36so1170804wyg.27 for ; Wed, 02 Nov 2011 16:02:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:from:date:message-id:subject:to :cc:content-type:content-transfer-encoding; bh=IakDbKw1ooEgPqR0tn/4JX2if+nq0JwZB10FkDQIrxo=; b=ZdnUmuDR+vmlm91us4hgrMpkPYBDC2nQiEx0VxFDTkdyQeZiOE9c9vPN9nUH5bfwdn ibeUJYBIysLrD3RsWQddYwU5/PRH8hZKGtZxcfIq67Ne+stl/EiBrNcuNGZBbzijHXgH T750VIu5Gy4e57UEXbUOLdWIcLtrS7fTZB0v0= Received: by 10.227.198.141 with SMTP id eo13mr8286646wbb.19.1320274937486; Wed, 02 Nov 2011 16:02:17 -0700 (PDT) MIME-Version: 1.0 Received: by 10.227.203.134 with HTTP; Wed, 2 Nov 2011 16:01:56 -0700 (PDT) In-Reply-To: References: <4EB1A5DB.8070405@gmail.com> From: Gabriel Scherer Date: Thu, 3 Nov 2011 00:01:56 +0100 Message-ID: To: Anthony Tavener Cc: caml-list@inria.fr Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 8bit X-MIME-Autoconverted: from quoted-printable to 8bit by walapai.inria.fr id pA2N2NNj031188 Subject: Re: [Caml-list] Nested module exposing type from parent? 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 > 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 >>> >> > > >