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,DNS_FROM_RFC_ABUSE autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail4-relais-sop.national.inria.fr (mail4-relais-sop.national.inria.fr [192.134.164.105]) by yquem.inria.fr (Postfix) with ESMTP id 25CCABC6B for ; Sat, 3 Nov 2007 23:15:36 +0100 (CET) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Ao8CAM6PLEfUGyojimdsb2JhbACBW40VAgEIAggREQc X-IronPort-AV: E=Sophos;i="4.21,367,1188770400"; d="scan'208";a="18909144" Received: from smtp5-g19.free.fr ([212.27.42.35]) by mail4-smtp-sop.national.inria.fr with ESMTP; 03 Nov 2007 23:15:35 +0100 Received: from smtp5-g19.free.fr (localhost.localdomain [127.0.0.1]) by smtp5-g19.free.fr (Postfix) with ESMTP id 144603F618F for ; Sat, 3 Nov 2007 23:15:35 +0100 (CET) Received: from Llea.celt.neu (ron34-3-82-236-236-194.fbx.proxad.net [82.236.236.194]) by smtp5-g19.free.fr (Postfix) with ESMTP id DE6BA3F617D for ; Sat, 3 Nov 2007 23:15:34 +0100 (CET) Received: from Llea.celt.neu (localhost [127.0.0.1]) by Llea.celt.neu (8.14.1/8.13.8) with ESMTP id lA3MKHDh008265 for ; Sat, 3 Nov 2007 23:20:17 +0100 (CET) (envelope-from michael.le_barbier@laposte.net) Received: (from michael@localhost) by Llea.celt.neu (8.14.1/8.13.8/Submit) id lA3MKGCi008264; Sat, 3 Nov 2007 23:20:16 +0100 (CET) (envelope-from michael.le_barbier@laposte.net) X-Authentication-Warning: Llea.celt.neu: michael set sender to michael.le_barbier@laposte.net using -f To: caml-list@yquem.inria.fr Subject: Strategy to avoid name collision in signatures From: michael.le_barbier@laposte.net (=?iso-8859-15?Q?Micha=EBl?= Le Barbier) Date: Sat, 03 Nov 2007 23:20:16 +0100 Message-ID: <86tzo3nf8f.fsf@Llea.celt.neu> User-Agent: Gnus/5.11 (Gnus v5.11) Emacs/22.1 (berkeley-unix) MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-15 Content-Transfer-Encoding: quoted-printable X-Spam: no; 0.00; functors:01 orderedtype:01 sig:01 val:01 orderedtype:01 functor:01 val:01 bool:01 struct:01 sig:01 struct:01 literate:01 noweb:01 camlp:01 chailloux:01 In some piece of code, I use functors combined with include as a kind of macro facility. In this scheme, it can happen that an identifier is exported multiple times from various include directives, this ``name collision'' is an error, and I am looking for ways to avoid it whithout much annoyance. (OK, this is very vague, details and example are coming.) Let's consider ordered types: one needs only a type and a compare function to define an ordered type, but one may agree that the signature module type OrderedType.PROTO =3D sig type t val compare: t -> t -> int end is a bit spartiat and wish for handy shortcuts such as ge, le, gt, lt, eq (ge means ``greater or equal'', and so on). As a tool to provide these handy shortcuts in signatures, let's define a OrderedType.Make functor that takes an OrderedType.PROTO and make an OrderedType.S: module type OderedType.S =3D type t val compare: t -> t -> int val ge: t -> t -> bool ... end Now, if one writes a module with a ``compare'' function, he can start with include OrderedType.Make(struct ... end) to get all these handy shortcuts at hand. Now, let's replicate the strategy, and define module type FunnyType.PROTO =3D sig type t =3D ... end module type FunnyType.S =3D sig type t =3D ... end module FunnyType.Make =3D ... This is a poor design, as one soon realizes, because one cannot write something like include OrderedType.Make(struct ... end) include FunnyType.Make(struct ... end) By doing so, one gets two definition for type `t', which is an error: Multiple definition of the type name t. Names must be unique in a given structure or signature. Of course, one can refrain to name every ``thingie'' type with ``t'', but this might break other requirements, so one will end up having duplicate content in module OrderedType. First part is the regular content above described, second part is replicating the regular content, with type t getting a new name (e.g. second part consists of modules S_ALT, Make_alt looking like S and Make with type t renamed to ordered_type_t; the input signature PROTO doed not need to be replicated). Having code duplicated is not an agile way of doing things (first kind of annoyance). Just saying module PreOrderedType =3D OrderedTypeMake(struct ... end) let ge =3D PreOrderedType.ge ... is totally inefficiant, since any change to OrderedType must be reflected in every place you use it (second kind of annoyance). Sure, one can generate appropriate lines automatically, but this is a far from ideal solution ... let's forget this one! It is also possible to rely on literate programming tool (such as NOWEB) to introduce a kind of macro capability and bypass the need of OrderedType.Make and FunnyType.Make. This is not an ideal solution as well (third kind of annoyance, cousin of second kind). I am looking for a way to handle this, that do not deviate too much from the non-working include OrderedType.Make(struct ... end) include FunnyType.Make(struct ... end) (solutions relying on camlp4/5 are an option, yet I cannot use this tool for now, because of my ignorance.) BTW, what's the purpose of ``include''? I did not remark any mention of it in Chailloux et al., and I wonder if the way I try to use it is weird or regular. Thanks a lot for having read this long article and for any light you could bring me up. --=20 Cheers, Micha=EBl LB