在OCaml中包含两个模块时处理类型名称冲突

时间:2012-06-18 11:05:17

标签: module include ocaml

任何人都可以帮我练习Jason Hickey的书吗?

基本上,问题是如何在实践中避免因“包含”引起的以下冲突问题?谢谢。

# module type XSig = sig 
type t 
val x : t 
end;; 
# module A : XSig = struct 
type t = int 
let x = 0 
end;; 
# module B : XSig = struct 
type t = int 
let x = 1 
end;; 
# module C = struct 
include A 
include B 
end;; 

1 个答案:

答案 0 :(得分:9)

我不知道究竟是什么问题,但是关于你的代码片段,有各种截然不同的方式来解释你想要做的事情。

您目前正在做的是将AB密封在两个抽象的,不兼容的签名下,然后尝试将它们混合在一个模块中,只是为了发生名称冲突。

也许你只是想避免名称冲突。当然,最简单的解决方案是不要对A.tB.t这两种类型使用相同的名称。然后你可以“不包括B”:

module C = struct
  include A
  let x_b = B.x
end

更好的解决方案是使用OCaml 3.12破坏性替换签名with type t := foo来掩盖模块t中的类型B

module C = struct
  include A
  type u = B.t (* rename B.t into 'u' to avoid name conflict *)
  include (B : XSig with type t := u)  (* replaces 't' by 'u' *)
end

您可能还希望模块AB的类型兼容。在这种情况下,你不能用抽象类型密封它们。

module type XSig = sig 
  type t 
  val x : t 
end

module A = struct 
  type t = int 
  let x = 0 
end

(* if you want to check that A can be sealed by XSig, do it here,
   outside the main declaration *)
let _ = (module A : XSig)

module B = struct 
  type t = int 
  let x = 1 
end

module C = struct 
  include (A : XSig with type t := int)
  include (B : XSig with type t := int)
end
(* module C : sig
     val x = int
   end *)

在此示例中,破坏性代理A.t删除了B.t:=这两种类型。如果您希望模块C的类型为t,则可以编写以下任一项:

module C = struct 
  type t = int
  include (A : XSig with type t := t)
  include (B : XSig with type t := t)
end

或使用非破坏性替换(更改类型定义而不是删除它):

module C = struct 
  include (A : XSig with type t = int)
  include (B : XSig with type t := t)
end

有关详细信息,请参阅manual page for destructive substitution type type t := ...;有关比较,请参阅the one on the classic with type t = ... construction