2017-09-01 102 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簽名隱含地定義你的模塊,這樣就不會有足夠的控制你的模塊,這就是爲什麼我建議你重新組織一下你的代碼(如果這不是問題)。