如何在OCaml中创建接口?可以通过创建接口文件foo.mli
和实现文件foo.ml
来创建具有单个实现的接口,但是如何为同一接口创建多个实现呢?
你必须使用模块和签名。一个.ml
文件隐含地定义了一个模块,而一个.mli
文件则定义了它的签名。通过显式地声明模块和签名,您可以将签名应用于多个不同的模块。
请参阅在线书籍《使用OCaml开发应用程序》的本章内容。
如果要为相同签名有多个实现,请将签名定义在编译单元内,而不是作为编译单元,并且(如果需要)对模块采取类似的方法。标准库中有一个示例:OrderedType
签名,它描述了具有类型和比较函数的模块:
module type OrderedType = sig
type t
val compare : t -> t -> int
end
这个签名同时在set.mli
和map.mli
中定义(你可以把它称为Set.OrderedType
或者Map.OrderedType
,甚至自己书写:签名是结构化的)。标准库中有几个编译单元具有此签名(如String
、Nativeint
等)。你也可以定义自己的模块,在定义模块时不需要做任何特殊处理:只要有一个叫做t
的类型以及一个值叫做compare
的类型为t -> t -> int
,该模块就具有该签名。标准库中还有一个稍微复杂的例子:Set.Make
函数式编程器构建了一个具有OrderedType
签名的模块,因此你可以通过这种方式构建集合的集合。
(* All four modules passed as arguments to Set.Make have the signature Set.OrderedType *)
module IntSet = Set.Make(module type t = int val compare = Pervasives.compare end)
module StringSet = Set.Make(String)
module StringSetSet = Set.Make(StringSet)
module IntSetSet = Set.Make(IntSet)