在OCaml中如何在mli文件和ml文件的签名之间共享结构体?

3
我最终要做的事情是: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相同的形状”约束,我不得不创建另一个名为`concat_type.ml`的`ml`文件,其内容如下:
(* concat_type.ml *)
module type TYPE = sig
  type t
  val concat : t -> t -> t
end
Concat_type.TYPEConcat mli在这种情况下几乎相同。我制作concat_type.ml的唯一原因是为了支持函数Join,并且明确限制它能够查看的内容,如果我尝试将其应用于模拟concat实现的模块,则可以避免重复问题。

有没有办法将Concat_type.TYPE导入到Concat接口中,反之亦然,或者其他方法来避免它们之间的重复?


1
你应该可以在concat.mli中使用“include Concat_type.TYPE”。 - glennsl
2
你可以使用 module type of Concat,例如,module Join (X : module type of Concat) : sig ... - gsg
1个回答

2

是的,可以通过 Concat_type.TYPE 模块类型来表达 Concat 模块接口。也可以获取现有模块的模块类型。

第一种方法如下:

(* concat.mli *)
include Concat_type.TYPE

第二种方法允许您摆脱 Concat_type,虽然我个人不喜欢它,因为我不喜欢 module type of 结构。但仍然有可能:
module type Concat = module type of Concat

module Join (X : Concat) = struct 
  ...
end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接