多个模块可以具有相同的模块类型吗?我如何组织它们和它们的接口文件?

Can multiple modules have the same module type? How do I organize them and their interface files?

目前,我在同一个 OCaml 文件中, blah.ml:

module type blah = 
 sig 
  val a : some-type
 end

module type X = 
 sig
  val x : some-type
 end

module Y : X = 
 struct
  let x = some-def
 end

module Z : X = 
 struct
  let x = some-other-def
 end

blah.mli 看起来像这样:

module type blah = 
 sig
  val a
 end

module type X = 
 sig
  val x : some-type
 end

module Y : X

module Z : X

我希望 X、Y 和 Z 位于具有不同界面的不同文件中。我如何在 Y.mli 和 Z.mli 中判断 Y 和 Z 的类型为 X?

如能阅读本文,我们将不胜感激。有很多资源都在谈论模块、接口和仿函数,但它们没有提到具有其他模块作为类型的模块的接口文件。

您可以创建包含 sig 的 x.ml、包含模块的 y.ml 和包含该模块的 z.ml。您不需要做任何特殊的事情来告诉编译器 Y : XZ : X。编译器根据模块符合类型的事实自动推断模块类型,即它实现模块类型需要的每个绑定。如果YZ不符合,使用时会提示类型错误。

如果您想在定义时限制模块类型,这也是可行的,方法是为每个模块提供一个接口文件,然后 include 在其中输入所需的签名。例如:

(* x.ml *)
module type S = sig
  val x : some-type
end

(* y.mli *)
include X.S

(* y.ml *)
let x = some-def

...等等。

然而,由于签名隐藏了太多关于类型的细节,这通常会变得过于严格。所以在现实中你可能真的需要添加类型相等共享约束来避免你想要暴露更多类型信息的编译错误。例如:

(* y.mli *)
include X.S with type t = int

通常根本没有显式接口文件会更容易,除非您确实需要将模块的某些部分设为私有。