From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Original-To: caml-list@sympa.inria.fr Delivered-To: caml-list@sympa.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id ED6687FE44 for ; Wed, 6 Jul 2016 09:49:54 +0200 (CEST) IronPort-PHdr: 9a23:J1McaxYx4Md8RzbzDjWN9zz/LSx+4OfEezUN459isYplN5qZpcWybnLW6fgltlLVR4KTs6sC0LuO9fq9EjVZsN6oizMrSNR0TRgLiMEbzUQLIfWuLgnFFsPsdDEwB89YVVVorDmROElRH9viNRWJ+iXhpQAbFhi3DwdpPOO9QteU1JXvkbrvsMSKMk1hv3mUWftKNhK4rAHc5IE9oLBJDeIP8CbPuWZCYO9MxGlldhq5lhf44dqsrtY4q3wD89pozcNLUL37cqIkVvQYSW1+ayFmrPHs4DvERgaL930raeQMlQYAVyrC5xz+T5G3iSbgsfZVxS+bI4j8VbswVC6n6KF3DhHy3nQpLTk8pUfWgct0hbkThxCsqxU36YfOKNWTNfF5eqrGO9QYSGZIGMxYTQRFD5O9YYpJBO0Ea7UL57LhrkcD+EPtTTKnA/nin3oR3if7 Authentication-Results: mail2-smtp-roc.national.inria.fr; spf=None smtp.pra=nicolas.ojeda.bar@lexifi.com; spf=None smtp.mailfrom=nicolas.ojeda.bar@lexifi.com; spf=None smtp.helo=postmaster@mx30.yaziba.net Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of nicolas.ojeda.bar@lexifi.com) identity=pra; client-ip=82.138.71.21; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="nicolas.ojeda.bar@lexifi.com"; x-sender="nicolas.ojeda.bar@lexifi.com"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of nicolas.ojeda.bar@lexifi.com) identity=mailfrom; client-ip=82.138.71.21; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="nicolas.ojeda.bar@lexifi.com"; x-sender="nicolas.ojeda.bar@lexifi.com"; x-conformance=sidf_compatible Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mx30.yaziba.net) identity=helo; client-ip=82.138.71.21; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="nicolas.ojeda.bar@lexifi.com"; x-sender="postmaster@mx30.yaziba.net"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: A0DxAADPtnxXfRVHilJdgnCBJHwBBbQ7hn0ihXYCgSkHPBABAQEBAQEBAREBAQsUCVCCMoIbAQQBEhEEUgULCQILLQoCAiISAQUBHAYTIogGCAQKjj6PQoExPjGLO49+AQEBBwEBAQEBASGKdIdBgloFmROGCYExhw2COIxyiBmGMhIegQ0CDyaCJxyBTmyIcgEBAQ X-IPAS-Result: A0DxAADPtnxXfRVHilJdgnCBJHwBBbQ7hn0ihXYCgSkHPBABAQEBAQEBAREBAQsUCVCCMoIbAQQBEhEEUgULCQILLQoCAiISAQUBHAYTIogGCAQKjj6PQoExPjGLO49+AQEBBwEBAQEBASGKdIdBgloFmROGCYExhw2COIxyiBmGMhIegQ0CDyaCJxyBTmyIcgEBAQ X-IronPort-AV: E=Sophos;i="5.28,318,1464645600"; d="scan'208,217";a="225752390" Received: from mx30.yaziba.net ([82.138.71.21]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 06 Jul 2016 09:49:53 +0200 Received: from mta20.int.yaziba.net (unknown [217.117.151.14]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx30.yaziba.net (mx10.yaziba.net) with ESMTPS id 9AAE81A74FF for ; Wed, 6 Jul 2016 09:49:52 +0200 (CEST) Received: from mta20.int.yaziba.net (localhost [127.0.0.1]) by mta20.int.yaziba.net (Postfix) with ESMTPS id AAAB4CA72A for ; Wed, 6 Jul 2016 09:49:52 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by mta20.int.yaziba.net (Postfix) with ESMTP id 9832FCA768 for ; Wed, 6 Jul 2016 09:49:52 +0200 (CEST) X-Virus-Scanned: amavisd-new at mta20.int.yaziba.net Received: from mta20.int.yaziba.net ([127.0.0.1]) by localhost (mta20.int.yaziba.net [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id SnED7mxoUo6O for ; Wed, 6 Jul 2016 09:49:52 +0200 (CEST) Received: from mail-qt0-f179.google.com (mail-qt0-f179.google.com [209.85.216.179]) by mta20.int.yaziba.net (Postfix) with ESMTPSA id 23E33CA773 for ; Wed, 6 Jul 2016 09:49:52 +0200 (CEST) Received: by mail-qt0-f179.google.com with SMTP id m2so112847695qtd.1 for ; Wed, 06 Jul 2016 00:49:52 -0700 (PDT) X-Gm-Message-State: ALyK8tLTt7RbP2bApzI0AkNndRX6EYUIGRxfffzhls7U2EcKSnXGx69vzUvrKoi1BchbUjm+A8Xp0SlUsqucRA== X-Received: by 10.200.34.19 with SMTP id o19mr33142836qto.97.1467791391005; Wed, 06 Jul 2016 00:49:51 -0700 (PDT) MIME-Version: 1.0 Received: by 10.237.49.2 with HTTP; Wed, 6 Jul 2016 00:49:31 -0700 (PDT) In-Reply-To: <64440D5D-1FC8-4C53-9520-D9D3D21F8FE5@univ-bpclermont.fr> References: <64440D5D-1FC8-4C53-9520-D9D3D21F8FE5@univ-bpclermont.fr> From: Nicolas Ojeda Bar Date: Wed, 6 Jul 2016 09:49:31 +0200 X-Gmail-Original-Message-ID: Message-ID: To: =?UTF-8?Q?Jocelyn_S=C3=A9rot?= Cc: OCaml Mailing List Content-Type: multipart/alternative; boundary=001a11394dbe7746430536f2d0e7 X-DRWEB-SCAN: ok X-VRSPAM-SCORE: -100 X-VRSPAM-STATE: legit X-VRSPAM-CAUSE: gggruggvucftvghtrhhoucdtuddrfeeltddrvdehgddufedtucetufdoteggodetrfcurfhrohhfihhlvgemucggtfgfnhhsuhgsshgtrhhisggvpdgjtegkkfeuteenuceurghilhhouhhtmecufedttdenucesvcftvggtihhpihgvnhhtshculddquddttddmnecujfgurhepjghfhfffkffuvfgtsegrtderredttdejnecuhfhrohhmpefpihgtohhlrghsucfqjhgvuggruceurghruceonhhitgholhgrshdrohhjvggurgdrsggrrheslhgvgihifhhirdgtohhmqeenucffohhmrghinhepuhhnihhvqdgsphgtlhgvrhhmohhnthdrfhhrpdhmhihsvghtrdhmlhdpmhihshgvthgrrdhmlhdpvgiguddrmhhlnecukfhppedvtdelrdekhedrvdduiedrudejleenucfrrghrrghmpehmohguvgepshhmthhpohhuth X-VRSPAM-EXTCAUSE: mhhouggvpehsmhhtphhouhht Subject: Re: [Caml-list] Q: functors and "has a" inheritance --001a11394dbe7746430536f2d0e7 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Hi Jocelyn One issue is that you have two modules, P and R.S, of the form Set.Make(X), Set.Make (X') for modules X and X' which are structurally equal. Unfortunately this is not enough for the OCaml module system to deduce that P.t and R.S.t are compatible. In general if F is a functor with output signature S and t is abstract type in S, then F(X).t and F(X').t will be compatible exactly when X and X' are literally the same module. I don't think you will be able to fix this by adding type sharing constrains. Cheers Nicolas On Tue, Jul 5, 2016 at 5:25 PM, Jocelyn S=C3=A9rot < Jocelyn.Serot@univ-bpclermont.fr> wrote: > Dear all, > > I=E2=80=99m stuck with a problem related with the use of functors for imp= lementing > a library. > The library concerns Labeled Transition Systems but i=E2=80=99ll present = it in a > simplified version using sets. > > Suppose i have a (very simplified !) Set module, which i will call Myset > to distinguish from that of the standard library : > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myset.mli > module type T =3D sig > type elt > type t > val empty: t > val add: elt -> t -> t > val elems: t -> elt list > val fold: (elt -> 'a -> 'a) -> t -> 'a -> 'a > end > > module Make (E : Set.OrderedType) : T with type elt =3D E.t > =E2=80=94=E2=80=94=E2=80=94 > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myset.ml > module type T =3D sig =E2=80=A6 (* idem myset.mli *) end > > module Make (E : Set.OrderedType) =3D struct > module Elt =3D E > type elt =3D E.t > type t =3D { elems: elt list; } > let empty =3D { elems =3D [] } > let add q s =3D { elems =3D q :: s.elems } (* obviously wrong, but doe= s not > matter here ! *) > let elems s =3D s.elems > let fold f s z =3D List.fold_left (fun z e -> f e z) z s.elems > end > =E2=80=94=E2=80=94=E2=80=94 > > First, i add a functor for computing the product of two sets : > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myset.mli (cont=E2=80=99d) > module Product (S1: T) (S2: T) : > sig > include T with type elt =3D S1.elt * S2.elt > val product: S1.t -> S2.t -> t > end > =E2=80=94=E2=80=94=E2=80=94 > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myset.ml (cont=E2=80=99d) > module Product > (S1: T) > (S2: T) =3D > struct > module R =3D > Make (struct type t =3D S1.elt * S2.elt let compare =3D compare end) > include R > let product s1 s2 =3D > S1.fold > (fun q1 z -> > S2.fold > (fun q2 z -> R.add (q1,q2) z) > s2 > z) > s1 > R.empty > end > =E2=80=94=E2=80=94=E2=80=94 > > Here=E2=80=99s a typical usage of the Myset module : > > =E2=80=94=E2=80=94 ex1.ml > module IntSet =3D Myset.Make (struct type t =3D int let compare =3D compa= re end) > module StringSet =3D Myset.Make (struct type t =3D string let compare =3D > compare end) > > let s1 =3D IntSet.add 1 (IntSet.add 2 IntSet.empty) > let s2 =3D StringSet.add "a" (StringSet.add "b" StringSet.empty) > > module IntStringSet =3D Myset.Product (IntSet) (StringSet) > > let s3 =3D IntStringSet.product s1 s2 > =E2=80=94=E2=80=94 > > So far, so good. > > Now suppose i want to =C2=AB augment =C2=BB the Myset module so that some= kind of > attribute is attached to each set element. I could of course just modify > the definition of type [t] and the related functions in the files [ > myset.ml] and [myset.mli]. But suppose i want to reuse as much as > possible the code already written. My idea is define a new module - let= =E2=80=99s > call it [myseta] (=C2=AB a =C2=BB for attributes) - in which the type [t]= will > include a type [Myset.t] and the definitions of this module will make use, > as much as possible, of those defined in [Myset]. > > Here=E2=80=99s a first proposal (excluding the Product functor for the mo= ment) : > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myseta.mli > module type Attr =3D sig type t end > > module type T =3D sig > type elt > type attr > type t > module S: Myset.T > val empty: t > val add: elt * attr -> t -> t > val elems: t -> elt list > val attrs: t -> (elt * attr) list > val set_of: t -> S.t > val fold: (elt * attr -> 'a -> 'a) -> t -> 'a -> 'a > end > > module Make (E : Set.OrderedType) (A: Attr) : T with type elt =3D E.t and > type attr =3D A.t > =E2=80=94=E2=80=94=E2=80=94 > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myseta.ml > module type Attr =3D sig type t end > > module type T =3D sig (* idem myseta.mli *) end > > module Make (E : Set.OrderedType) (A : Attr) =3D struct > module Elt =3D E > type elt =3D E.t > type attr =3D A.t > module S =3D Myset.Make(E) > type t =3D { elems: S.t; attrs: (elt * attr) list } > let empty =3D { elems =3D S.empty; attrs =3D [] } > let add (e,a) s =3D { elems =3D S.add e s.elems; attrs =3D (e,a) :: s.a= ttrs } > let elems s =3D S.elems s.elems > let attrs s =3D s.attrs > let set_of s =3D s.elems > let fold f s z =3D List.fold_left (fun z e -> f e z) z s.attrs > end > =E2=80=94=E2=80=94=E2=80=94 > > In practice, of course the [Attr] signature will include other > specifications. > In a sense, this is a =C2=AB has a =C2=BB inheritance : whenever i build = a [Myseta] > module, i actually build a [Myset] sub-module and this module is used to > implement all the set-related operations. > Again, so far, so good. > The problem shows when i try to define the [Product] functor for the > [Myseta] module : > It=E2=80=99s signature is similar to that of the [Myset.Product] functor,= with an > added sharing constraint for attributes (in fact, we could imagine a more > sophisticated scheme for merging attributes but cartesian product is here= ) : > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myset.mli (cont=E2=80=99d) > module Product (S1: T) (S2: T) : > sig > include T with type elt =3D S1.elt * S2.elt > and type attr =3D S1.attr * S2.attr > val product: S1.t -> S2.t -> t > end > =E2=80=94=E2=80=94=E2=80=94 > > Now, here=E2=80=99s my current implementation > > =E2=80=94=E2=80=94=E2=80=94=E2=80=94 myset.ml (cont=E2=80=99d) > module Product > (S1: T) > (S2: T) =3D > struct > module R =3D > Make > (struct type t =3D S1.elt * S2.elt let compare =3D compare end) > (struct type t =3D S1.attr * S2.attr let compare =3D compare end) > include R > module P =3D Myset.Product(S1.S)(S2.S) > let product s1 s2 =3D > { elems =3D P.product (S1.set_of s1) (S2.set_of s2); > attrs =3D > List.fold_left > (fun acc (e1,a1) -> > List.fold_left (fun acc (e2,a2) -> ((e1,e2),(a1,a2))::acc) > acc (S2.attrs s2)) > [] > (S1.attrs s1) } > end > =E2=80=94=E2=80=94=E2=80=94 > > I use the [Myseta.Make] functor for building the resulting module [named R > here]. For defining the [product] function, i first use the [Myset.Produc= t] > functor applied on the two related sub-modules [S1] and [S2] to build the > product module (named P here) and re-use the [product] function of this > module to compute the [elems] component of the result. The other component > is computed directly. > The problem is that when i try to compile this i get this message : > > *File "myseta.ml ", line 44, characters 14-53:* > *Error: This expression has type P.t =3D Myset.Product(S1.S)(S2.S).t* > * but an expression was expected of type S.t =3D R.S.t* > > My intuition is that a sharing constraint is missing somewhere but i just > cannot figure out where to add it. > I tried to rewrite the signature of the [Myseta.Product] functor (in > [myseta.mli]) as : > > module Product (S1: T) (S2: T) : > sig > include T with type elt =3D S1.elt * S2.elt > and type attr =3D S1.attr * S2.attr > and type S.t =3D Myset.Product(S1.S)(S2.S).t (* added > constraint *) > val product: S1.t -> S2.t -> t > end > > but it did not change anything.. > > So my question is : is my diagnostic correct and, if yes, which > constraint(s) are missing and where; or, conversely, am i completely > =C2=AB misusing =C2=BB the functor mechanisms for implementing this kind = of =C2=AB reuse > by inclusion =C2=BB ? > > Any help will be grealy appreciated : i=E2=80=99ve been reading and re-re= ading > about functors for the last two days but have the impression that at this > step, things get more and more opaque.. :-S > > In anycase, the source code is here : > http://filez.univ-bpclermont.fr/lamuemlqpm > > Jocelyn > --001a11394dbe7746430536f2d0e7 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable
Hi Jocelyn

One issue is that you have t= wo modules, P and R.S, of the form Set.Make(X), Set.Make (X') for modul= es X and X' which are structurally equal.=C2=A0 Unfortunately this is n= ot enough for the OCaml module system to deduce that P.t and R.S.t are comp= atible.=C2=A0 In general if F is a functor with output signature S and t is= abstract type in S, then F(X).t and F(X').t will be compatible exactly= when X and X' are literally the same module.=C2=A0 I don't think y= ou will be able to fix this by adding type sharing constrains.
Cheers
Nicolas


On Tue, Jul 5, 2016 at 5:25= PM, Jocelyn S=C3=A9rot <Jocelyn.Serot@univ-bpclermont.fr> wrote:
Dear all,=C2=A0

I=E2=80=99m stuck with a= problem related with the use of functors for implementing a library.
=
The library concerns Labeled Transition Systems but i=E2=80=99ll prese= nt it in a simplified version using sets.

Suppose = i have a (very simplified !) Set module, which i will call Myset to disting= uish from that of the standard library :

=E2=80=94=E2=80=94=E2=80=94=E2= =80=94=C2=A0myset.mli
module type T =3D sig
=C2=A0 type elt=C2=A0
=C2=A0 type t=C2=A0
=C2=A0 val empt= y: t
=C2= =A0 val add: elt -> t -> t
=C2=A0 val elems: t -> elt list
= =C2=A0 val fold: (elt ->= 'a -> 'a) -> t -> 'a -> 'a
end

module Make (E : Set.OrderedType) : T wi= th type elt =3D E.t
=E2=80=94=E2=80=94=E2=80=94=C2=A0
=

module type T =3D sig=C2=A0=E2=80=A6 (* id= em myset.mli *) end

= module Make (E : Set.OrderedType) =3D struct=
=C2=A0 module Elt =3D E
= =C2=A0 type elt =3D E.t
<= div>=C2=A0 type t =3D= { elems: elt list; } =C2=A0
=C2=A0 let empty =3D { elems =3D [] }
= =C2=A0 let add q s =3D { elems =3D q :: s.elems } =C2=A0(* obviously wrong,= but does not matter here ! *)
=C2=A0 let elems s =3D s.elems
=C2=A0 = let fold f s z =3D List.fold_left (fun z e -> f e z) z s.elems
end
=E2=80=94=E2=80=94=E2=80=94=C2=A0

First, i add a functor for computing the product of two sets :
<= br>
= =E2=80=94=E2=80=94=E2=80=94=E2=80=94=C2=A0myset.mli (cont=E2=80=99d)=
module Product (S1: T) (S2: T) :
sig
=C2=A0 include T with type elt= =3D S1.elt * S2.elt
=C2=A0 val product: S1.t -> S2.t -> t<= /font>
end<= /span>
=E2=80=94=E2=80=94=E2=80=94=C2=A0

=
=E2=80=94=E2=80= =94=E2=80=94=E2=80=94=C2=A0my= set.ml (cont=E2=80=99d)
module Product
= =C2=A0 (S1: T)=
=C2= =A0 (S2: T) =3D
struct
<= span style=3D"font-size:11px">=C2=A0 module R =3D
<= font face=3D"Courier">=C2=A0 =C2=A0 Make=C2= =A0(struct= =C2=A0type t =3D = S1.elt * S2.elt=C2=A0let compare =3D compare=C2=A0end)
=C2=A0 =C2=A0 include R
=C2=A0 =C2=A0 let product s1 s2= =3D
=C2=A0 =C2=A0 =C2=A0 S1.fold
=C2=A0 =C2=A0 =C2=A0 =C2=A0 (fun q1= z ->
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0S2.fold<= /div>
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(fun q2 z -> R.add (q1,q2) z)
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0s2
= =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0z)
=C2=A0 =C2=A0 =C2=A0 =C2=A0 s1
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 R.empty
end
=E2=80=94=E2=80=94=E2=80=94=C2=A0=

Here=E2=80=99s a typical usage of the Myset mod= ule :=C2=A0

=E2=80=94=E2=80=94 ex1.ml=C2=A0
module IntSet =3D Myset.Make (struct ty= pe t =3D int let compare =3D compare end)
module StringSet =3D Myset.Mak= e (struct type t =3D string let compare =3D compare end)

let s1 = =3D IntSet.add 1 (IntSet.add 2 IntSet.empty)
let s2 =3D StringSet.add &q= uot;a" (StringSet.add "b" StringSet.empty)

module IntStringSet =3D Myset.Product (IntSet) (StringSet)

<= /font>
let = s3 =3D IntStringSet.product s1 s2
=E2=80=94=E2=80= =94

So far, so good.=C2=A0

Now suppose i want to =C2=AB=C2=A0augment=C2=A0=C2=BB the Myset mod= ule so that some kind of attribute is attached to each set element. I could= of course just modify the definition of type [t] and the related functions= in the files [myset.ml] = and [myset.mli]. But suppose i want to reuse as much as possible the code a= lready written. My idea is define a new module - let=E2=80=99s call it [mys= eta] (=C2=AB=C2=A0a=C2=A0=C2=BB for attributes) - in which the type [t] wil= l include a type [Myset.t] and the definitions of this module will make use= , as much as possible, of those defined in [Myset].

Here=E2=80=99s a first proposal (excluding the Product functor for the mo= ment) :=C2=A0

=E2=80=94=E2=80=94=E2=80=94=E2=80=94=C2=A0myseta.mli=
module type Attr =3D sig type t end

module type T =3D s= ig
=C2=A0 type elt=C2=A0
= =C2=A0 type attr
=C2=A0 type t=C2=A0
= =C2=A0 module S: Myset.T
=C2=A0 val empty: t
=C2=A0 val add: elt * at= tr -> t -> t
=C2=A0 val elems: t -> elt list
=C2=A0 val attr= s: t -> (elt * attr) list
=C2=A0 val set_of: t -> S.t
=C2=A0 va= l fold: (elt * attr -> 'a -> 'a) -> t -> 'a -> &= #39;a
end

module Make (E : Set.OrderedType) (A: Attr) : T wit= h type elt =3D E.t and type attr =3D A.t
=E2=80=94=E2=80=94=E2=80= =94=C2=A0

=E2=80=94=E2=80=94=E2=80=94=E2=80=94=C2=A0myseta.ml
module type A= ttr =3D sig type t end

module type T =3D sig (* idem myseta.mli = *) end

module Make (E : Set.OrderedType) (A : Attr) =3D s= truct
=C2=A0 module Elt =3D E
=C2=A0 type elt =3D E.t
=C2=A0 type = attr =3D A.t
=C2=A0 module S =3D Myset.Make(E)
<= font face=3D"Courier">=C2=A0 type t =3D { el= ems: S.t; attrs: (elt * attr) list }
=C2=A0 let empty =3D { elems =3D S.= empty; attrs =3D [] }
=C2=A0 let add (e,a) s =3D { elems =3D S.add e s.e= lems; attrs =3D (e,a) :: s.attrs }
=C2=A0 let elems s =3D S.elems s.elem= s
=C2=A0 let attrs s =3D s.attrs
=C2=A0 let set_of s =3D s.elems
= =C2=A0 let fold f s z =3D List.fold_left (fun z e -> f e z) z s.attrs
end
=E2=80=94=E2=80=94=E2=80=94=C2=A0
<= br>
In practice, of course the [Attr] signature will include othe= r specifications.
In a sense, this is a =C2=AB=C2=A0has a=C2=A0= =C2=BB inheritance : whenever i build a [Myseta] module, i actually build a= [Myset] sub-module and this module is used to implement all the set-relate= d operations.=C2=A0
Again, so far, so good.
The problem= shows when i try to define the [Product] functor for the [Myseta] module :=
It=E2=80=99s signature is similar to that of the [Myset.Product]= functor, with an added sharing constraint for attributes (in fact, we coul= d imagine a more sophisticated scheme for merging attributes but cartesian = product is here) :

=E2=80=94=E2=80=94=E2=80=94=E2=80=94=C2=A0myset= .mli (cont=E2=80=99d)
<= span style=3D"font-size:11px">module Product (S1: T) (S2: T) :
sig
= =C2=A0 include T with type elt =3D S1.elt * S2.elt
= =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0and type attr =3D S1.attr * S2.attr
=C2=A0 val p= roduct: S1.t -> S2.t -> t
end
=E2=80=94=E2=80=94=E2=80=94=C2=A0<= /span>

Now, here=E2=80=99s my current implem= entation

=E2=80=94=E2=80=94=E2=80=94=E2=80=94=C2=A0myset.ml (cont=E2=80=99d)
modu= le Product
=C2=A0 (S1: T)
=C2=A0 (S2: T) =3D
= struct<= /div>
=C2=A0 modu= le R =3D
=C2=A0 =C2=A0 Make
=C2=A0 =C2=A0 =C2=A0 (struct type t =3D S= 1.elt * S2.elt let compare =3D compare end)
=C2=A0 =C2=A0 =C2=A0 (struct= type t =3D S1.attr * S2.attr let compare =3D compare end)
=C2=A0 includ= e R
=C2=A0 module P =3D Myset.Product(S1.S)(S2.S)
=C2=A0 let product s1 s2 =3D
=C2=A0 =C2= =A0 { elems =3D P.product (S1.set_of s1) (S2.set_of s2);
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0attrs =3D
=C2=A0 =C2=A0 =C2=A0 =C2=A0 List.fol= d_left
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 (fun acc (e1,a1) -><= /font>
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0List.fold_left=C2=A0(fun acc (e2,a2) -&g= t; ((e1,e2),(a1,a2))::acc)=C2=A0acc=C2=A0(S2.attrs s2))
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 []
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 (S1.attrs s1) }
end
<= span style=3D"font-size:11px;font-family:Courier">=E2=80=94=E2=80=94=E2=80= =94=C2=A0

I use the [Myseta.Make] fun= ctor for building the resulting module [named R here]. For defining the [pr= oduct] function, i first use the [Myset.Product] functor applied on the two= related sub-modules [S1] and [S2] to build the product module (named P her= e) and re-use the [product] function of this module to compute the [elems] = component of the result. The other component is computed directly.=C2=A0
The problem is that when i try to compile this i get this message := =C2=A0

File "myseta.ml", line 44, characters 14-53:<= /div>
Error: This expression has type P.t =3D Myset.Product(S1.S)(S2= .S).t
=C2=A0 =C2=A0 =C2=A0 =C2=A0but an expression was exp= ected of type S.t =3D R.S.t

My in= tuition is that a sharing constraint is missing somewhere but i just cannot= figure out where to add it.=C2=A0
I tried to rewrite the signatu= re of the [Myseta.Product] functor (in [myseta.mli]) as :

module P= roduct (S1: T) (S2: T) :
sig
=C2=A0 include T with type elt =3D S1.el= t * S2.elt
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0and type attr= =3D S1.attr * S2.attr
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0a= nd type S.t =3D Myset.Product(S1.S)(S2.S).t =C2=A0(* added constraint *)
=C2=A0 val product: S1.t -> S2.t -> t
end

but it did not change anything..

=
So my question is : is my diagnostic correct and, if yes, which constr= aint(s) are missing and where; or, conversely, am i completely =C2=AB=C2=A0= misusing=C2=A0=C2=BB the functor mechanisms for implementing this kind of = =C2=AB=C2=A0reuse by inclusion=C2=A0=C2=BB ?=C2=A0

Any help will be grealy appreciated : i=E2=80=99ve been reading and re-rea= ding about functors for the last two days but have the impression that at t= his step, things get more and more opaque.. :-S

In= anycase, the source code is here :=C2=A0http://filez.univ-bpclermont.fr/lamu= emlqpm

Jocelyn

--001a11394dbe7746430536f2d0e7--