2011-03-17 99 views
2

我已經定義了兩個模塊的類型和兩個模塊使用「與類型」結構在模塊

module type FOO = sig type e end 
module type BAR = sig type t end  
module Foo : FOO = struct type e = int end 
module Bar : BAR = struct type t = int end 

當放鬆類型檢查然後我定義一個算符作爲

module Fun (F:FOO) (B:BAR with type t = F.e) = struct type x = string end 

(這是一個玩具示例請忽略FB不使用函子的事實)

現在,如果我定義模塊

module Bla = Fun (Foo) (Bar) 

我得到

Error: Signature mismatch: 
     Modules do not match: 
     sig type t = Bar.t end 
     is not included in 
     sig type t = Foo.e end 
     Type declarations do not match: 
     type t = Bar.t 
     is not included in 
     type t = Foo.e 

雖然這兩個Bar.tFoo.eint OCaml的考慮Bar.tFoo.e是不同的定義。這就是鍵入系統的工作方式,通常考慮這兩種類型是有意義的(c.f. Functors and Type Abstraction的最後一段)。

問題有時我可能想這個通過類型檢查,因爲我的目的,它們可以被認爲是相等的。有什麼方法可以放鬆嗎?去除脅迫


使用gasche的建議,上述代碼可以寫爲

module type FOO = sig type e end 
module type BAR = sig type t end 
module Foo = struct type e = int end 
module Bar = struct type t = int end 
module Fun (F : FOO with type e=int) (B : BAR with type t = int) = struct type x = F.e * B.t end 
module Bla = Fun (Foo) (Bar) 

其中編譯罰款。奇怪的是,我得到

# let f x : Bla.x = (x,x);; 
val f : Foo.e -> Bla.x = <fun> 

問題:爲什麼它推斷xFoo.e?它可能是Bar.t

回答

5

問題是你如何定義FooBarmodule Foo : FOO = ...。通過在這裏強加這個簽名,您可以「密封」模塊並進行類型抽象。它無法恢復。您應該在這裏刪除: FOO強制,並在需要抽象時稍後使用它。您也可以使用module Foo : (FOO with type e = int) = ...

+0

確定,不夠公平。我會盡可能晚的離開強制。有一些關於做這聽起來不太好,但我有的代碼(其中以上是一個玩具的例子)現在正在工作,所以我會忍受。謝謝! – Surikator 2011-03-17 20:47:58

0

我不知道打印機如何選擇同等類型之中,但在這種情況下,你可能會導致它被明確標註你的函數參數打印不同的名稱:

# let f (x:Bar.t) : Bla.x = (x,x);; 
val f : Bar.t -> Bla.x = <fun>