2017-04-19 187 views
0

所以,當你定義模塊的結構,它可以延長另一個模塊關閉它:擴展遞歸模塊

module Base = struct 
    type t = Name of string 
end 

module Child = struct 
    include Base 
end 

Child.Name "test" 
(* - : Child.t = Child.Name "test" *) 

然而,隨着recursive modules using recursive signatures工作時,我遇到問題時,我嘗試延長模塊:

module rec Base : sig 
    type t = | Name of string 
end = Base 

and Child : sig 
    include Base 
end = Child 

當我這樣做,我得到一個錯誤說:

Error: Unbound module type Base 

在使用此遞歸模塊技巧時,您不能擴展模塊嗎?我誤會了什麼或做錯了什麼?

+0

我想補充一點,遠離遞歸模塊是個好主意。 –

+0

@ÉtienneMillon怎麼回事?你有什麼文章可以把我和這件事聯繫起來嗎? –

+0

這被標記爲實驗性的,並且受到手冊中的重大更改的影響,類型推斷被降級,您不能將它們放在單獨的文件中。我認爲過去有健全的錯誤。打破遞歸或者在類型和值之間移動它幾乎總是最好的解決方案。 –

回答

1

在我看來,你的問題是,Base是一個模塊,而不是一個模塊類型。當包含在sig ... end構造中時,您需要一個類型。當包含在struct ... end構造中時,您需要一個模塊。這就是爲什麼第一個例子有效,而第二個例子沒有。

如果我改變Basemodule type of Base我得到這個錯誤:

Error: Illegal recursive module reference 

所以我懷疑這個特殊的(有些奇怪)類型遞歸定義的不支持。

如果分別定義模塊類型,你可以把它的工作:

module type BASE = sig type t = Name of string end 

module rec Base : BASE = Base 

and Child : sig 
    include BASE 
end = Child 
+0

這是有道理的;我無法在簽名定義中包含模塊的定義。謝謝Jeffrey –

+0

如果你不介意單獨定義模塊類型,你可以得到你想要的結構(見上文)。 –

0

傑弗裏·斯科菲爾德已經給了很好的回答。我只想補充說include只是語法糖。因此,如果是include這會給您帶來麻煩,解決方案可能是將其展開。在你的第一個例子中,將導致

module Base = struct 
    type t = Name of string 
end 

module Child = struct 
    type t = Name of string 
end 

顯然,你的例子是你真正想做的簡化版本。如圖所示,根本不需要使用rec。所以我只能猜測你真的需要多少遞歸。根據Jeffrey Scofield的回答,recinclude的組合是有問題的。可能的是,擺脫include就足夠了。