任何人都可以帮我练习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;;
答案 0 :(得分:9)
我不知道究竟是什么问题,但是关于你的代码片段,有各种截然不同的方式来解释你想要做的事情。
您目前正在做的是将A
和B
密封在两个抽象的,不兼容的签名下,然后尝试将它们混合在一个模块中,只是为了发生名称冲突。
也许你只是想避免名称冲突。当然,最简单的解决方案是不要对A.t
和B.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
您可能还希望模块A
和B
的类型兼容。在这种情况下,你不能用抽象类型密封它们。
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。