2017-09-01 61 views
1

我想扩展一个模块,但我需要访问其私有组件。这里有一个例子:在OCaml中公开模块扩展的私有类型

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在签名中,并且定义natext_nat与私人type t。你怎么看?

回答

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签名隐含地定义你的模块,这样就不会有足够的控制你的模块,这就是为什么我建议你重新组织一下你的代码(如果这不是问题)。