如何合并定义相同类型的OCaml模块类型(签名)?

jac*_*ev6 10 ocaml

在OCaml中,我有两种定义类型的模块类型t:

module type Asig = sig
    type t
    val a : t
end

module type Bsig = sig
    type t
    val b : t
end
Run Code Online (Sandbox Code Playgroud)

我想自动创建合并它们的模块类型.我想创建一个等效于的模块类型:

module type ABsig_manual = sig
    type t
    val a : t
    val b : t
end
Run Code Online (Sandbox Code Playgroud)

我试过了

module type ABsig = sig
    include Asig
    include Bsig
end
Run Code Online (Sandbox Code Playgroud)

但这失败了Error: Multiple definition of the type name t.似乎不可能添加类型约束,include所以我被卡住了.

上下文:我有一个AB实现两个签名的模块,我想将它提供给一个仿函数,如:

module MakeC(AB) = struct
    type t = AB.t list
    let c = [AB.a; AB.b]
end

module C = MakeC(AB)
Run Code Online (Sandbox Code Playgroud)

我可以使用两个参数:

module UglyMakeC(A : Asig)(B : Bsig with type t = A.t) = struct
    type t = A.t list
    let c = [A.a; B.b]
end

module C = UglyMakeC(AB)(AB)
Run Code Online (Sandbox Code Playgroud)

但是这个(丑陋的)并不能很好地扩展到更多的仿函数或更多的签名来合并.

那么,如何自动合并这两种模块类型呢?我可以根据需要修改A和B,但我希望将它们分开.此外,也许我的方法是完全错误的,在这种情况下,我喜欢指向更好的方向.

OCaml中的类型共享 - 类型检查错误是相关的,但合并模块,而不是模块类型.

Dru*_*rup 17

这是做到这一点的方法:

module type Asig = sig
    type t
    val a : t
end

module type Bsig = sig
    type t
    val b : t
end

module type ABsig = sig
    include Asig
    include Bsig with type t := t
end
Run Code Online (Sandbox Code Playgroud)

它被称为"破坏性替代".

  • 为了将来参考,这在"语言扩展","在签名内替换"段落(http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234)中有记载,它扩展了所描述的内容.在"The OCaml Language"中,"模块类型"一节(http://caml.inria.fr/pub/docs/manual-ocaml/modtypes.html). (4认同)
  • Real World OCaml(第 186-187 页)针对这种情况提出了一种替代解决方案,解释说“[t] 在组合多个接口时更清晰一些,因为它正确地反映了所有签名都被同等处理”:`模块类型 ABsig = sig 类型 t 包括类型为 t 的 Asig := t 包括类型为 t 的 Bsig := t end` (2认同)