Dear list,

My question is about how to hide modules (or parts thereof) in
an ocaml package from the outside world (users of the package).

I am trying to build an ocaml package with internal functionality
(types and functions)
that I do not want to expose. I have two modules in the package implemented by
foo.ml and bar.ml. The structure of each .mli looks like this:

> module Foo = sig
>   type t
>   val make : t
>   val change : t -> t
>
>   (* Internal, not to be exposed. *)
>   val unsafe_change : t -> t
> end

> module Bar = sig
>   type t
>   val combine : t -> Foo.t -> t (* uses unsafe_change *)
> end

As you see Foo exports unsafe_change because Bar needs it.
I compile both modules using "-for-pack Foobar" and build them using
the "-pack" option.
However, now I want to hide "Foo.unsafe_change" from the package
"export list" (if there
is such a thing) so that main.ml cannot call it. I see the following options:

* Merge foo.ml and bar.ml so that unsafe_change does not need to be exposed.
  I don't like this, the modules could be very large.
* Split Foo into Foo_internal and Foo, and somehow keep Foo_internal
  invisible. I don't know how to do this. I would use "exposed-modules" in
  Cabal which is a package manager for Haskell.
* Add the file foobar.mli which contains the signatures of Foo and Bar
but hiding
  Foo.unsafe_change. I think it could work, but I would have to repeat
much of the Foo
  and Bar interfaces. I tried this but it didn't work, ocaml complains
as follows:

> Error: The implementation (obtained by packing)
>        does not match the interface foobar.mli:
>        The field `Foo' is required but not provided

  I am attaching a tarball of this attempt in case someone knows what
went wrong.
  The example is a bit different from the example in the email.

So the question is:

  What solution do you follow when you want to hide (part of) a module
in a package?
  Keep in mind that the hidden parts should still be exposed to the
modules inside
  the package.

A related question is how to expose the representation Foo.t so that
Bar can manipulate it
directly, but at the same time keep it hidden from users of the
package. The following easy
hack works. Create foo_type.mli with the definition of the type t:

> type t = int

and redefine Foo as follows:

> module Foo = sig
>   type t = Foo_type.t
>   val make : t
>   val change : t -> t
>
>   (* Internal, not to be exposed. *)
>   val unsafe_change : t -> t
> end

Now "t" is visible for Bar to use but we still have to hide it from
the outside world. How do
we do it? Well, just use "-pack" on foo.cmx and bar.cmx. We can omit
Foo_types because it has
no .cmx. As a consequence Foo.t becomes abstract. This probably works
by accident and maybe it
is not a good idea to rely on this trick.

I would appreciate if you can share your experiences and perhaps point
to some ocaml library
that does module or partial module hiding so I can use it as an example.

Thank you!

Cheers,

Alexey

Attachment: packages.tgz
Description: GNU Zip compressed data

_______________________________________________
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

Reply via email to