caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Avoiding ml/mli code duplication
@ 2010-12-28 14:02 Lauri Alanko
  2010-12-28 14:16 ` Richard W.M. Jones
  2010-12-28 14:59 ` Alain Frisch
  0 siblings, 2 replies; 4+ messages in thread
From: Lauri Alanko @ 2010-12-28 14:02 UTC (permalink / raw)
  To: caml-list

A common grievance with ML-style module systems is duplication of code
between the interface and the implementation of a module. In
particular, transparent type and signature definitions must be present
in both. This is annoying because of the extra work required to keep
both copies in sync.

To an extent, this can be avoided. Consider the following:


(*** Foo.mli ***)
(* Transparent definitions *)
type t = ...
module type S = sig ... end
(* Opaque definitions depending on the above *)
val x : ... t ...
module M : ... S ... t ...

(*** Foo.ml ***)
(* Transparent definitions duplicated *)
type t = ...
module type S = sig ... end
(* Definitions for the opaques *)
let x = ...
module M = ...


Here the common transparent definitions can be moved into a separate
wholly transparent module:


(*** FooDefs.ml ***)
type t = ...
module type S = sig ... end

(*** Foo.ml ***)
include module type of FooDefs (* or open FooDefs *)
val x : ... t ...
module M : ... S ... t ...

(*** Foo.mli ***)
include FooDefs (* or open FooDefs *)
let x = ...
module M = ...


So far so good. But in the real world, the situation is often more
complicated: we have transparent definitions that depend on opaque
definitions. Like this:


(*** Bar.mli ***)
(* Opaque *)
type t
(* Transparent depending on above *)
type u = ... t ...
(* Opaque depending on above *)
val x : ... u ...

(*** Bar.ml ***)
type t = ...
type u = ... t ...
let x = ...


Keep in mind that in actuality the "type u" line can represent huge
amounts of type and signature definitions, so there is real need to
avoid duplication.

In this situation, I'm not quite sure what's the best way to
proceed. Here's what I have currently:

(*** BarDefs.ml ***)
module type CORE = sig
  (* Primitive opaque definitions that the transparents depend on *)
  type t
end
module Make(Core : CORE) = struct
  include Core
  (* Transparent definitions *)
  type u = ... t ...
end

(*** Bar.mli ***)
module Core : BarDefs.CORE
include module type of BarDefs.Make(Core)
val x : ... u ...

(*** Bar.ml ***)
module Core = struct
  type t = ...
end
include BarDefs.Make(Core)
let x = ...


This does the job, but I'm not quite satisfied. It feels wrong that I
have to define a functor when I will only ever apply it once. Also,
the "include module type of" is a recent feature, and it's hard to
believe there's no solution to this problem before OCaml 3.12.

I'd appreciate any suggestions for better solutions.


Lauri

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

end of thread, other threads:[~2010-12-28 16:54 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-12-28 14:02 [Caml-list] Avoiding ml/mli code duplication Lauri Alanko
2010-12-28 14:16 ` Richard W.M. Jones
2010-12-28 14:59 ` Alain Frisch
2010-12-28 16:54   ` Lauri Alanko

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).