我最终要做的事情是1)限制对模块的可见性(因此mli文件)和2)定义一个仿函数,其中参数具有"规范实现"它作为ml
/ mli
对存在于源树中,并坚持认为参数具有与此规范实现相同的形状。
假设我有一个文件concat.ml
,其中包含一个字符串连接函数
(* concat.ml *)
type t = string
let concat x y = x ^ y
我有一个界面
(* concat.mli *)
type t
val concat : t -> t -> t
但是,我也有一个仿函数join
看起来像这样,并期望与Concat
具有相同形状的东西。 (join
的实施是故意天真的):
(* 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
为了表达与Concat相同的形状"约束,我必须制作另一个ml
文件concat_type.ml
,如下所示:
(* concat_type.ml *)
module type TYPE = sig
type t
val concat : t -> t -> t
end
在这种情况下, Concat_type.TYPE
和Concat
mli几乎相同。我提出concat_type.ml
的唯一原因是支持仿函数Join
,并明确限制它可以看到的内容,如果我尝试将其应用于模仿concat
实现的模块。
有没有办法将Concat_type.TYPE
导入Concat
界面,反之亦然或以其他方式导入,以避免它们之间的重复?
答案 0 :(得分:1)
是的,可以通过Concat
模块类型表达Concat_type.TYPE
模块接口。也可以获得现有模块的模块类型。
第一种方法如下:
(* concat.mli *)
include Concat_type.TYPE
第二种方法允许你摆脱Concat_type
,虽然我个人不喜欢它,因为我不喜欢module type of
构造。但仍有可能:
module type Concat = module type of Concat
module Join (X : Concat) = struct
...
end