2017-10-17 48 views
2

我最终试图做的事情是1)限制对模块(因此mli文件)的可见性和2)定义一个函子,其中参数具有“规范实现“,它作为一个ml/mli对生活在源码树中,并坚持参数具有与此规范实现相同的形状。mml文件和ml文件里签名之间的OCaml共享结构

假设我有一个包含字符串连接

(* concat.ml *) 
type t = string 
let concat x y = x^y 

单一功能的文件concat.ml和我有一个接口,它

(* 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 

为了表达“相同形状的毗连”的约束,我只好再拍ml文件concat_type.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_type.TYPE'在concat.mli,我觉得 – glennsl

+2

你可以用'Concat'的模块类型,例如,'模块加入(X:Concat的模块类型):sig ...'。 – gsg

回答

1

是的,可以通过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