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

15
在OCaml中,我有两个模块类型来定义类型t:
module type Asig = sig
    type t
    val a : t
end

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

我希望自动化创建合并模块类型。我想要创建一个等同于以下模块类型的模块:
module type ABsig_manual = sig
    type t
    val a : t
    val b : t
end

我尝试过

module type ABsig = sig
    include Asig
    include Bsig
end

但是,使用时会出现“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)

我可以像这样使用两个参数:

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)

但是这种方式(丑陋且)无法很好地扩展到更多的函子或要合并的签名。那么,我该如何自动合并这两种模块类型? 我可以根据需要修改A和B,但我想保持它们分开。此外,也许我的方法完全错误,如果是这种情况,我希望能获得更好方向的指引。OCaml中的类型共享-类型检查器错误与此相关,但合并的是模块而不是模块类型。

你考虑过在 caml-list@inria.fr 上询问吗? - Basile Starynkevitch
1个回答

25
这是实现它的方法:

以下是具体步骤:

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

它被称为“破坏性替换”。

4
以后参考,这个内容记录在“语言扩展”章节的“替换签名内部”段落中(http://caml.inria.fr/pub/docs/manual-ocaml/extn.html#sec234),该段落扩展了“OCaml语言”中描述的“模块类型”一节(http://caml.inria.fr/pub/docs/manual-ocaml/modtypes.html)。 - jacquev6
1
更持久的参考链接:http://caml.inria.fr/pub/docs/manual-ocaml-4.07/extn.html#sec249(ref手册中的secXXX锚点会随着每个新版本的OCaml而修改) - jacquev6
3
《Real World OCaml》(第186-187页)提出了一种解决这种情况的替代方案,解释道:“当组合多个接口时,这种方法会更加清晰,因为它正确地反映了所有签名的等效处理”:module type ABsig = sig type t include Asig with type t := t include Bsig with type t := t end - fishyfriend

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