Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[Caml-list] Extending modules and signatures

2 views
Skip to first unread message

Peter Hawkins

unread,
Apr 17, 2009, 4:51:54 PM4/17/09
to caml...@yquem.inria.fr
Hi...

I have a quick question. I want to extend the List module with various
functions that I want that aren't present in the standard library,
much as the Batteries ExtList library does.

I might write the following code in "mylibrary.ml":
module MyList = struct
include List
let foo x = ... code here
let bar y = ... code here
end

That's ok so far, but now suppose I want to write a "mylibrary.mli"
interface file corresponding to "mylibrary.ml". Ideally I'd write
something like this in "mylibrary.mli":
module MyList : sig
include List (* unknown module type List *)
val foo : ...
val bar : ...
end

Unfortunately I can't include "List" here since it is a structure, not
a signature. I don't think there is a way to say "include the
signature associated with List".

I can think of three solutions:
a) Copy the complete signature of List into MyList. This is a bad idea
since the List module might change in the future. This is what the
Batteries ExtList module does.
b) Alter the List module to define a signature, say List.S, in
addition to its other contents. I can't easily do this since I didn't
write the List module.
c) Don't write a .mli file at all.

Are there any other alternatives?

Cheers,
Peter

_______________________________________________
Caml-list mailing list. Subscription management:
http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list
Archives: http://caml.inria.fr
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
Bug reports: http://caml.inria.fr/bin/caml-bugs

Dario Teixeira

unread,
Apr 17, 2009, 5:30:32 PM4/17/09
to caml...@yquem.inria.fr, Peter Hawkins

Hi,


> I have a quick question. I want to extend the List module with various
> functions that I want that aren't present in the standard library,
> much as the Batteries ExtList library does.

I reckon you want something like this:

http://caml.inria.fr/mantis/view.php?id=3013

Cheers,
Dario Teixeira

Goswin von Brederlow

unread,
Apr 17, 2009, 5:36:45 PM4/17/09
to Peter Hawkins, caml...@yquem.inria.fr
Peter Hawkins <hawk...@cs.stanford.edu> writes:

Something like :

module MyList = struct
include List

module M : sig val foo : int -> unit end = struct
let foo x = ()
let bar y = y
end
include M
end

and no .mli file. The module M is there to alow you to give (or hide)
the signature of just your extra functions.

> Cheers,
> Peter

MfG
Goswin

Ashish Agarwal

unread,
Apr 18, 2009, 1:48:05 AM4/18/09
to Peter Hawkins, caml...@yquem.inria.fr
This is a commonly requested feature. One issue is that a file a.ml creates
a module A. However, a file a.mli does not create a module type A. I'm not
sure why this is the case. Does anyone know if there is a specific reason?

Martin Jambon

unread,
Apr 18, 2009, 10:24:04 AM4/18/09
to Ashish Agarwal, caml...@yquem.inria.fr
Ashish Agarwal wrote:
> This is a commonly requested feature.

Ah.

> One issue is that a file a.ml

> <http://a.ml> creates a module A. However, a file a.mli does not create


> a module type A. I'm not sure why this is the case. Does anyone know if
> there is a specific reason?

The module type exists, it's just that it doesn't have a name.

let x = (123, "abc")

does not define "type x = int * string" either.

Martin

--
http://mjambon.com/

Ashish Agarwal

unread,
Apr 19, 2009, 5:36:24 PM4/19/09
to Martin Jambon, caml...@yquem.inria.fr
> The module type exists, it's just that it doesn't have a name.
Right, thanks for the clarification.


> let x = (123, "abc")
> does not define "type x = int * string" either.

True, but I think the expectations are different for module types. A file
a.ml creates a module named A, and it seems natural to expect a.mli to
create a module type A. I find it inconsistent that it does not.

Further, if you wanted to name the above type, it is easy, just write "type
x = int * string". The corresponding solution to naming module types is
burdensome. You have to define it within another module, introducing an
unnecessary layer into your module hierarchy. Also that doesn't help you
when using somebody else's library.

Having the compiler introduce module type names automatically from mli files
would be very helpful, and I don't see any disadvantages.

On Sat, Apr 18, 2009 at 10:20 AM, Martin Jambon
<martin...@ens-lyon.org>wrote:

Jon Harrop

unread,
Apr 19, 2009, 5:46:33 PM4/19/09
to caml...@yquem.inria.fr
On Sunday 19 April 2009 22:36:12 Ashish Agarwal wrote:
> > The module type exists, it's just that it doesn't have a name.
>
> Right, thanks for the clarification.
>
> > let x = (123, "abc")
> > does not define "type x = int * string" either.
>
> True, but I think the expectations are different for module types. A file
> a.ml creates a module named A, and it seems natural to expect a.mli to
> create a module type A. I find it inconsistent that it does not.

The mli and ml are equivalent to:

module A : sig =
...
end = struct
...
end

i.e. no module type is defined.

> Further, if you wanted to name the above type, it is easy, just write "type
> x = int * string". The corresponding solution to naming module types is
> burdensome. You have to define it within another module, introducing an
> unnecessary layer into your module hierarchy. Also that doesn't help you
> when using somebody else's library.

True. There is also an unfortunate amount of copy'n'paste involved as well,
and manual maintenance of signatures. I believe that often deters people from
using module signatures and module types at all.

> Having the compiler introduce module type names automatically from mli
> files would be very helpful, and I don't see any disadvantages.

Some people contest the idea that files should automatically convey module
information at all (SML does not). Indeed, should directories convey
something as well?

--
Dr Jon Harrop, Flying Frog Consultancy Ltd.
http://www.ffconsultancy.com/?e

Martin Jambon

unread,
Apr 19, 2009, 8:10:06 PM4/19/09
to Ashish Agarwal, caml...@yquem.inria.fr
Ashish Agarwal wrote:
>> The module type exists, it's just that it doesn't have a name.
>
> Right, thanks for the clarification.
>
>
>> let x = (123, "abc")
>> does not define "type x = int * string" either.
>
> True, but I think the expectations are different for module types. A
> file a.ml <http://a.ml> creates a module named A, and it seems natural

> to expect a.mli to create a module type A. I find it inconsistent that
> it does not.
>
> Further, if you wanted to name the above type, it is easy, just write
> "type x = int * string". The corresponding solution to naming module
> types is burdensome. You have to define it within another module,
> introducing an unnecessary layer into your module hierarchy. Also that
> doesn't help you when using somebody else's library.
>
> Having the compiler introduce module type names automatically from mli
> files would be very helpful, and I don't see any disadvantages.

OK, but I think the real issue is inheritance. In order to truly extend an
existing module, one needs to access the private items of the inherited module
implementation. In order to avoid messing up with the original module's
global variables, the inherited "module" should be more like a functor that
would create a fresh instance of the module each time it is instantiated, just
like classes generate objects.


I could imagine something like this:

module class A :
sig
val get_x : unit -> int
end =
struct
let x = ref 123
let get_x () = !x
end

module class B =
struct
inherit A
let incr_x () = incr x
end

module B1 = new module B
module B2 = new module B
;;

B1.incr_x ();;
- : unit = ()
B1.get_x ();;
- : int = 124
B2.get_x ();;
- : int = 123


Module class implementations and signatures could be conveniently created as
whole files using new file extensions, say .mc and .mci. These would be like
ml files except that they would support module class inheritance and would be
evaluated only when they are instantiated with "new module".

Goswin von Brederlow

unread,
Apr 20, 2009, 1:18:14 AM4/20/09
to caml...@yquem.inria.fr
Jon Harrop <j...@ffconsultancy.com> writes:

> On Sunday 19 April 2009 22:36:12 Ashish Agarwal wrote:
>> Having the compiler introduce module type names automatically from mli
>> files would be very helpful, and I don't see any disadvantages.
>
> Some people contest the idea that files should automatically convey module
> information at all (SML does not). Indeed, should directories convey
> something as well?

I thought they did.

a.ml: module B = struct let foo = ... end

and

a/b.ml : let foo = ...

could actually be equivalent and both result in A.B.foo.

MfG
Goswin

Goswin von Brederlow

unread,
Apr 20, 2009, 1:23:31 AM4/20/09
to Martin Jambon, caml...@yquem.inria.fr
Martin Jambon <martin...@ens-lyon.org> writes:

> .ml files except that they would support module class inheritance and would be


> evaluated only when they are instantiated with "new module".

Which would also need

module A1 = new module A
module A2 = new module A
A1.incr_x ()
A1.get_x;;
- : int = 124
A2.get_x ();;
- : int = 123

So you see A does not have global variables but only instance
variables. What you describe are ocaml objects. Not modules.

MfG
Goswin

Martin Jambon

unread,
Apr 20, 2009, 7:59:37 AM4/20/09
to Goswin von Brederlow, caml...@yquem.inria.fr
Goswin von Brederlow wrote:
> Which would also need
>
> module A1 = new module A
> module A2 = new module A
> A1.incr_x ()
> A1.get_x;;
> - : int = 124
> A2.get_x ();;
> - : int = 123
>
> So you see A does not have global variables but only instance
> variables. What you describe are ocaml objects. Not modules.

The tiny <ahem> difference is that objects may not contain type definitions.
Functors do, but they don't support inheritance because all the private
members are hidden behind the module interface.

Martin

--
http://mjambon.com/

Ashish Agarwal

unread,
Apr 21, 2009, 12:01:13 PM4/21/09
to Martin Jambon, caml...@yquem.inria.fr
> I think the real issue is inheritance.
Yes. Your example adds an extra complication by using references. Forgoing
that, I get around this within the current module system by defining a base
module B, which two other modules C an D "inherit", i.e. they just include
B. Module B has the common values and types needed by C and D. Only problem
with this is that I am forced to expose all the values and types in B to all
client code. It would help to restrict B's visibility to just C and D. No
big deal for internally used libraries; I just remember not to use B
elsewhere. However, it is not a good solution for libraries distributed to
others.


On Sun, Apr 19, 2009 at 8:06 PM, Martin Jambon
<martin...@ens-lyon.org>wrote:

> .ml files except that they would support module class inheritance and would

0 new messages