2

我想扩展一个模块,但我需要访问它的私有组件。这是一个例子:

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 = intnatext_nattype t

4

1 回答 1

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 中构造自己,所以你对你的模块没有足够的控制权,这就是为什么我建议你稍微重新组织你的代码(如果这不是问题的话)。

于 2017-09-01T16:26:31.973 回答