我想扩展模块,但我需要访问其私有组件。这是一个例子:
nat.mli:
type t
val zero : t
val succ : t -> t
nat.ml:
type t = int
let zero = 0
let succ x = x + 1
我想定义一个定义Ext_nat
函数的新模块double
。我试图做这样的事情。
ext_nat.mli:
include (module type of Nat)
val double : t -> t
ext_nat.ml:
include Nat
let double x = 2 * x
它没有工作,因为我无法访问最后一行中x
的代表。
现在我正在思考这个问题,无论如何这可能不是一个好主意,因为这会破坏nat
的封装。那么最好的方法是什么?我可以在签名中定义nat_public
其中type t = int
的新模块,并使用私有nat
定义ext_nat
和type t
。你觉得怎么样?
答案 0 :(得分:1)
您需要使用with type
声明。可以用许多不同的方式编写下面的代码,但这个想法总是一样的。
module type NatSig =
sig
type t
val zero : t
val succ : t -> t
end
module type ExtNatSig =
sig
include NatSig
val double : t -> t
end
module ExtNat : ExtNatSig =
struct
type t = int
let zero = 0
let succ = fun x -> x + 1
let double = fun x -> x * 2
end
module Nat = (ExtNat : NatSig with type t = ExtNat.t)
let z = Nat.zero
let _ = ExtNat.double z
问题在于,据我所知,使用您的文件结构无法实现此行为:您使用.mli文件中的签名隐式定义模块,并在.ml中构造自身,因此您无法控制你模块,这就是为什么我建议你稍微重新组织你的代码(如果这不是问题)。