我最终要做的事情是:1)限制模块的可见性(因此需要mli文件),2)定义一个函数,其中参数具有在源代码树中作为ml/mli对存在的“规范实现”,并且要求参数具有与此规范实现相同的形状。
假设我有一个名为concat.ml的文件,其中包含一个用于字符串连接的函数。
为了表达“与Concat相同的形状”约束,我不得不创建另一个名为`concat_type.ml`的`ml`文件,其内容如下:
假设我有一个名为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相同的形状”约束,我不得不创建另一个名为`concat_type.ml`的`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
接口中,反之亦然,或者其他方法来避免它们之间的重复?
module type of Concat
,例如,module Join (X : module type of Concat) : sig ...
。 - gsg