Reputation: 6994
The thing I'm ultimately trying to do is 1) restrict visibility into a module (hence the mli file) and 2) define a functor where the argument has a "canonical implementation" that lives in the source tree as an ml
/mli
pair and insists that arguments have the same shape as this canonical implementation.
Suppose I have a file concat.ml
that contains a single function for string concatenation
(* concat.ml *)
type t = string
let concat x y = x ^ y
and I have an interface for it
(* concat.mli *)
type t
val concat : t -> t -> t
However, I also have a functor join
that looks like this and expects something with the same shape as Concat
. (The implementation of join
is intentionally naive):
(* join.ml *)
module Join(X : Concat_type.TYPE) : sig
val join : X.t list -> X.t
end = struct
let rec join xs = match xs with
| [] -> failwith "can't be empty"
| [x] -> x
| [x; y] -> X.concat x y
| (x::xs') -> X.concat x (join xs')
end
In order to express the "same shape as Concat" constraint, I've had to make another ml
file concat_type.ml
that looks like this:
(* concat_type.ml *)
module type TYPE = sig
type t
val concat : t -> t -> t
end
Concat_type.TYPE
and the Concat
mli are nearly identical in this case. The only reason I made concat_type.ml
at all was to support the functor Join
and explicitly restrict what it can see if I try to apply it to a module mimicking the implementation of concat
.
Is there a way to import Concat_type.TYPE
into the Concat
interface or vice versa or some other way to avoid duplication between them?
Upvotes: 3
Views: 511
Reputation: 35210
Yes, it is possible to express the Concat
module interface via the Concat_type.TYPE
module type. It is also possible to get a module type of an existing module.
The first approach looks like this:
(* concat.mli *)
include Concat_type.TYPE
The second approach allows you to get rid of the Concat_type
, though I personally dislike it, as I don't like the module type of
construct. But still, there is a possibility:
module type Concat = module type of Concat
module Join (X : Concat) = struct
...
end
Upvotes: 2