简体   繁体   中英

OCaml share structure between mli file and signature inside ml file

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM