From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.5 required=5.0 tests=AWL autolearn=disabled version=3.1.3 Received: from mail3-relais-sop.national.inria.fr (mail3-relais-sop.national.inria.fr [192.134.164.104]) by yquem.inria.fr (Postfix) with ESMTP id C9C8CBBAF for ; Sat, 23 Aug 2008 18:42:23 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AucCAC/br0jAXQIniGdsb2JhbACRbD4BAQEPIJpJhmQBAoNugS0 X-IronPort-AV: E=Sophos;i="4.32,259,1217800800"; d="scan'208";a="16220757" Received: from concorde.inria.fr ([192.93.2.39]) by mail3-smtp-sop.national.inria.fr with ESMTP; 23 Aug 2008 18:41:50 +0200 Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by concorde.inria.fr (8.13.6/8.13.6) with ESMTP id m7NGfnec001902 for ; Sat, 23 Aug 2008 18:41:50 +0200 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AjwBAIvar0jRVcbvmmdsb2JhbACRbD4BAQEBAQgFCAcRA5pHhmQBAoNugS0 X-IronPort-AV: E=Sophos;i="4.32,259,1217800800"; d="scan'208";a="28449296" Received: from rv-out-0506.google.com ([209.85.198.239]) by mail4-smtp-sop.national.inria.fr with ESMTP; 23 Aug 2008 18:40:01 +0200 Received: by rv-out-0506.google.com with SMTP id k40so780728rvb.57 for ; Sat, 23 Aug 2008 09:40:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from:sender :to:subject:cc:in-reply-to:mime-version:content-type :content-transfer-encoding:content-disposition:references :x-google-sender-auth; bh=8GLR56O+hSTPryTYkOGq4Wkn/Fo72lXcZdtqucuDDP4=; b=YeTbV8x1fKKpXUfguj+nwollkY350YGLr4d5f9dKnGsX8BJOl5Dp4sSjkdsYg4AXvA D5PHymHhqoIZVa5HnP4gnLTN7utlSu1otc3HGIwRaKAtfkxlK4LqIAEjB+RXEL+s+TDh /EYJ01xFSU9uScNvLlS3RYD2X1zGkNgHEXDJo= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:sender:to:subject:cc:in-reply-to:mime-version :content-type:content-transfer-encoding:content-disposition :references:x-google-sender-auth; b=fBidF3hbFPuOt2xVJTQrza89Z1OHX5yNwCD2sqJbcdXdrSGC+eT7Uj1ViVJvQmvUjD pqzZcqhg8xnZCZ5SHzh6d72UXHG+V4syWyUEujE0ENFhQccmXPqhQoZtPDvCNU7HE/34 0o0vA91E2cQBBtw1NAjhmSR4mizuEcWuahwcA= Received: by 10.142.223.20 with SMTP id v20mr879346wfg.81.1219509600458; Sat, 23 Aug 2008 09:40:00 -0700 (PDT) Received: by 10.142.105.11 with HTTP; Sat, 23 Aug 2008 09:40:00 -0700 (PDT) Message-ID: <2b7b425b0808230940r58c6d4f6t6b06f12a2e1bb52b@mail.gmail.com> Date: Sat, 23 Aug 2008 18:40:00 +0200 From: "=?ISO-8859-1?Q?J=E9r=E9mie_Lumbroso?=" Sender: jeremie.lumbroso@gmail.com To: "Keiko Nakata" Subject: Re: [Caml-list] Separating two mutually recursive modules Cc: caml-list@inria.fr In-Reply-To: <20080822.175619.125115724.keiko@kurims.kyoto-u.ac.jp> MIME-Version: 1.0 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline References: <2b7b425b0808201654i61d3f878gbed5c27ca9114438@mail.gmail.com> <20080821.182901.68534700.keiko@kurims.kyoto-u.ac.jp> <2b7b425b0808210400j618e461fre54f73612b920e4a@mail.gmail.com> <20080822.175619.125115724.keiko@kurims.kyoto-u.ac.jp> X-Google-Sender-Auth: 69a33fb20694a2d6 X-Miltered: at concorde with ID 48B03DCD.000 by Joe's j-chkmail (http://j-chkmail . ensmp . fr)! X-Spam: no; 0.00; recursive:01 typechecker:01 sig:01 val:01 struct:01 variants:01 flags:01 recursive:01 functors:01 functor:01 functor:01 sig:01 anil:01 node:01 val:01 Hello, Thank you for your attempts ... I know of the "double vision" problem, and I am actually confused by the post which you reference. I think it discusses an old version of the typechecker, as the example which Xavier Leroy gives supposedly to illustrate the flaw now (3.10.2) properly type-checks: module rec M : sig type t val f : t -> t end =3D struct type t =3D int let f (x : M.t) =3D x end http://caml.inria.fr/pub/ml-archives/caml-list/2007/06/0d23465b5b04f72fedec= dd3bbf2c9d72.en.html XL also mentions a solution for this problem: resorting to variants, so Caml explicitly flags the type, thus preventing it from "forgetting" how a given type was defined. I wonder if the specific problem which was solved by this hack still exists (and if it is in fact the problem that I'm encountering here). Do you (or anybody else) have any idea (if I can /) how to adapt the "variant hack" to my problem ... And for the record, here is the latest (failed) rewrite of my modules. I basically just did the same thing for the umpteenth time (abstract all recursive/external references with local types, and then use "with" conditions to try to coerce these). I have however identified very clearly what is missing. The problem is that recursivity is not fully supported with functors: if it were then it would be possible to "reference" the arguments before they are bound. Currently, I have: module rec BMk : functor(Boxes : BOXES) -> functor (Validator : VALIDATOR with type bbt =3D Boxes.B.t) -> What I would need is: module rec BMk : functor(Boxes : BOXES with type vt =3D Validator.t and type bat =3D Boxes.A.t) -> functor (Validator : VALIDATOR with type bbt =3D Boxes.B.t) -> However, of course, Caml tells me that "Validator" is unbound. I suspect this is what you've tried to do yourself (a wrapper module which defines all "argument" modules as a recursive set of modules, which can then be mutually recursively referenced). Am I wrong? All the best, J=E9r=E9mie (****************) (* MODULE Boxes *) (****************) module type BOXES =3D sig type vt (* Validator.t *) type bat (* Boxes.A.t *) (* NOTE: I which modules A and B where only accessible by Boxes itself, but not by Validator. (And have something such as type t =3D B.t) *) module A : sig (* This type was simplified for explanatory purposes. *) type t =3D private | Anil | Aout of vt end module B : sig type t =3D private | Bnil | Bout of bat * t end end module type VALIDATOR =3D sig type bbt (* Boxes.B.t *) (* This type has been simplified for explanatory purposes. *) type t =3D Me of int | Node of t * t | B of bbt val fold_on_B : (bbt -> 'a) -> ('a -> 'a -> 'a) -> 'a -> t -> 'a end module rec BMk : functor(Boxes : BOXES) -> functor (Validator : VALIDATOR with type bbt =3D Boxes.B.t) -> BOXES with type vt =3D Validator.t and type bat =3D Boxes.A.t =3D functor (Boxes : BOXES) -> functor (Validator : VALIDATOR with type bbt =3D Boxes.B.t) -> struct type vt =3D Validator.t type bat =3D Boxes.A.t module rec A : sig type t =3D | Anil | Aout of vt val boolfold : ('a -> bool) -> ('a -> bool) -> bat -> bool end =3D struct type t =3D | Anil | Aout of vt let boolfold p1 p2 =3D let rec aux =3D function | Boxes.A.Anil -> false | Boxes.A.Aout elt -> Validator.fold_on_B (fun x -> B.boolfold p1 p2 x) (||) false = elt in aux end and B : sig type t =3D | Bnil | Bout of A.t * t val boolfold : ('a -> bool) -> ('a -> bool) -> Boxes.B.t -> bool end =3D struct type t =3D | Bnil | Bout of A.t * t let boolfold p1 p2 =3D let rec aux =3D function | Boxes.B.Bnil -> false | Boxes.B.Bout(a, elt) -> (A.boolfold p1 p2 a) || (aux elt) in aux end end (********************) (* MODULE Validator *) (********************) module rec VMk : ( functor(Validator : VALIDATOR) -> functor (Boxes : BOXES with type vt =3D Validator.t) -> VALIDATOR with type bbt =3D Boxes.B.t ) =3D functor(Validator : VALIDATOR) -> functor (Boxes : BOXES) -> struct type bbt =3D Boxes.B.t type t =3D Me of int | Node of t * t | B of bbt (* This functions must allow me to do "fold-like" operations on object of type t, specifically targetting nodes of type B of Boxes.B.t *) let fold_on_B f combinator default =3D let rec aux =3D function (* Recursive calls down the tree. *) | Node(b1, b2) -> combinator (aux b1) (aux b2) (* Leaves which must be processed. *) | B r -> f r (* Leaves which must be ignored, and return the default value. *) | _ -> default in aux end