caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Strategy to avoid name collision in signatures
@ 2007-11-03 22:20 Michaël Le Barbier
  2007-11-03 22:47 ` [Caml-list] " Andrej Bauer
  2007-11-04  0:01 ` Julien Moutinho
  0 siblings, 2 replies; 5+ messages in thread
From: Michaël Le Barbier @ 2007-11-03 22:20 UTC (permalink / raw)
  To: caml-list

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 =
  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 =
    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 = sig type t = ... end
  module type FunnyType.S = sig type t = ... end
  module FunnyType.Make = ...


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 = OrderedTypeMake(struct ... end)
  let ge = 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.
-- 
Cheers,
Michaël LB


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Strategy to avoid name collision in signatures
  2007-11-03 22:20 Strategy to avoid name collision in signatures Michaël Le Barbier
@ 2007-11-03 22:47 ` Andrej Bauer
  2007-11-04  6:15   ` Michaël Le Barbier
  2007-11-04  0:01 ` Julien Moutinho
  1 sibling, 1 reply; 5+ messages in thread
From: Andrej Bauer @ 2007-11-03 22:47 UTC (permalink / raw)
  To: Michaël Le Barbier; +Cc: caml-list

Michaël Le Barbier wrote:
>   include OrderedType.Make(struct ... end)
>   include FunnyType.Make(struct ... end)

Can you give a convincing example that would prevent you from separating
these two with tsubmodules, i.e.,

module AsOrd = OrderedType.Make(struct ... end)
module AsFunny = FunnyType.Make(struct ... end)

If you really want to "blend" together OrderedType and FunnyType in the
same module, then they must be meaningfully related. What example do you
have in mind?

Andrej


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Strategy to avoid name collision in signatures
  2007-11-03 22:20 Strategy to avoid name collision in signatures Michaël Le Barbier
  2007-11-03 22:47 ` [Caml-list] " Andrej Bauer
@ 2007-11-04  0:01 ` Julien Moutinho
  2007-11-04  7:34   ` Michaël Le Barbier
  1 sibling, 1 reply; 5+ messages in thread
From: Julien Moutinho @ 2007-11-04  0:01 UTC (permalink / raw)
  To: caml-list

On Sat, Nov 03, 2007 at 11:20:16PM +0100, Michaël Le Barbier wrote:
> 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.)
[...]

I'm not sure if it could be of some help, but here is another scheme
wherein the functor <name>Type.Make does not include its argument PROTO,
so that there is no namespace conflict with type t.
However the PROTO structure can no longer be used anonymously:

    include OrderedType.Make(struct type t let compare : t -> t -> int = Pervasives.compare end)

Gives the error message:

    This functor has type
    functor (PROTO : OrderedType.PROTO) ->
      sig val ge : PROTO.t -> PROTO.t -> bool end
    The parameter cannot be eliminated in the result type.
     Please bind the argument to a module identifier

The module identifier <name>Type_PROTO should be ok.

module OrderedType =
  struct
    module type PROTO =
      sig type t val compare : t -> t -> int end
    module Make
      (PROTO: PROTO) =
      struct let ge t t' = PROTO.compare t t' >= 0 end
  end
module FunnyType =
  struct
    module type PROTO =
      sig type t val compare : t -> t -> int end
    module Make
      (PROTO: PROTO) =
      struct let funny_ge t t' = PROTO.compare t t' >= 0 end
  end
module OrderedType_PROTO =
  struct type t let compare : t -> t -> int = Pervasives.compare end
module FunnyType_PROTO =
  struct type t let compare : t -> t -> int = Pervasives.compare end
include OrderedType.Make(OrderedType_PROTO)
include FunnyType.Make(FunnyType_PROTO)

Which gives:

module OrderedType :
  sig
    module type PROTO = sig type t val compare : t -> t -> int end
    module Make :
      functor (PROTO: PROTO) ->
      sig val ge : PROTO.t -> PROTO.t -> bool end
  end
module FunnyType :
  sig
    module type PROTO = sig type t val compare : t -> t -> int end
    module Make :
      functor (PROTO: PROTO) ->
      sig val funny_ge : PROTO.t -> PROTO.t -> bool end
  end
module OrderedType_PROTO : sig type t val compare : t -> t -> int end
module FunnyType_PROTO   : sig type t val compare : t -> t -> int end
val ge       : OrderedType_PROTO.t -> OrderedType_PROTO.t -> bool
val funny_ge : FunnyType_PROTO.t -> FunnyType_PROTO.t -> bool

HTH,
  Julien.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Strategy to avoid name collision in signatures
  2007-11-03 22:47 ` [Caml-list] " Andrej Bauer
@ 2007-11-04  6:15   ` Michaël Le Barbier
  0 siblings, 0 replies; 5+ messages in thread
From: Michaël Le Barbier @ 2007-11-04  6:15 UTC (permalink / raw)
  To: Andrej.Bauer; +Cc: Michaël Le Barbier, caml-list

Andrej Bauer <Andrej.Bauer@fmf.uni-lj.si> writes:

> If you really want to "blend" together OrderedType and FunnyType in the
> same module, then they must be meaningfully related. What example do you
> have in mind?

A real example is where FunnyType.Make will add conveniance functions
to a ring structure (math rings). Let's say FunnyType.PROTO defines

  ...
  one: t
  zmul: int -> t ->t
  ...

FunnyProto.Make will add few functions to this interface, e.g.

  mone: t (= zmul (-1) one)
  two: t (= zmul 2 one)

-- 
All the best,
Michaël LB


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [Caml-list] Strategy to avoid name collision in signatures
  2007-11-04  0:01 ` Julien Moutinho
@ 2007-11-04  7:34   ` Michaël Le Barbier
  0 siblings, 0 replies; 5+ messages in thread
From: Michaël Le Barbier @ 2007-11-04  7:34 UTC (permalink / raw)
  To: Julien Moutinho; +Cc: caml-list

Julien Moutinho <julien.moutinho@gmail.com> writes:

> I'm not sure if it could be of some help, but here is another scheme
> wherein the functor <name>Type.Make does not include its argument PROTO,
> so that there is no namespace conflict with type t.
> However the PROTO structure can no longer be used anonymously:

This is fine. Here's how I will work it out:

module Ordered =
struct

  module type PROTO =
    type t
    val compare: t -> t -> int
  end

  module type S =
    type t
    val compare: t -> t -> int
    val ge: t -> t -> bool
  end

  module Macro (P:PROTO) =
  struct
    let ge x y = (compare x y) >= 0
  end

  module Make (P:PROTO) =
  struct
    type t = P.t
    include Macro(P)
  end

end


It seems as economic as possible, provided I want to provide both the
`Macro' and `Make' version. Thanks for the hint!
-- 
Cordialement,
Michaël LB


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2007-11-04  7:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-03 22:20 Strategy to avoid name collision in signatures Michaël Le Barbier
2007-11-03 22:47 ` [Caml-list] " Andrej Bauer
2007-11-04  6:15   ` Michaël Le Barbier
2007-11-04  0:01 ` Julien Moutinho
2007-11-04  7:34   ` Michaël Le Barbier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).