2017-08-06 80 views
0

1)假設有一個模塊OCAML第一類模塊簽名推理

module Int_Sig_1 = 
struct 
let x = 1 
end 
;; 

2)和該模塊

module type INT_SIG = 
sig 
val x:int 
end 
;; 

3)的顯式簽名和我創建基於第一級模塊在上面的模塊和模塊類型

let int_sig_1 = (module Int_Sig_1:INT_SIG) 

4)現在我創建另一個模塊沒有明確的簽名,但推斷的同一個signat URE如上

module Int_Sig_2 = 
struct 
let x =2 
end 
;; 

5)寫在現實世界OCAML的第10章「模塊類型並不需要是一個一流的模塊建設的一部分,如果可以推斷」我嘗試使用上述模塊創建第二個第一類模塊,但沒有明確的模塊類型

let a2 = (module Int_Sig_2);; 

我收到以下錯誤

Error: The signature for this packaged module couldn't be inferred.

6)然後我嘗試做與上述相同的5,但是是我把一級模塊沒有模塊類型被創建爲一個列表的元素,其中列表的頭部是第一個類模塊,它是在上面3中的顯式簽名中創建的。

let int_sig= [int_sig_1;(module Int_Sig_2)];; 
val int_sig : (module INT_SIG) list = [<module>; <module>] ;; 

我的問題是,爲什麼5上面給我一個錯誤和6不會失敗?

回答

2

與(5)的是,在一般情況下,有可能被多個infered模塊類型的問題。在你的榜樣,有可能被用來包裝Int_Sig_2至少兩個有效的模塊類型:

module type empty = sig end 
module type with_x = sig val x:int end 

換句話說,無論

let a2 = (module Int_Sig_2: empty) 
let a2_bis = (module Int_Sig_2:with_x) 

是有效的。因此,在這種情況下,類型檢查器不會嘗試推斷出模塊類型。

相反,在您的示例(6)中,列表的類型由其第一個元素確定,其類型爲(module INT_SIG_2),因此類型檢查器可以使用此信息來推斷第二個元素的預期類型該列表是(module INT_SIG_2)。不過,顛倒這兩個元素會產生類型錯誤。換句話說,這是好的:

[(module struct let x = 2 end: with_x); (module struct let x = 1 end)] 

然而,反向收率

[(module struct let x=2 end); (module struct let x = 3 end:with_x)];; 
Error: The signature for this packaged module couldn't be inferred. 

這是由於該類型檢查器具有左到右的偏壓和類型第一所述事實首先列表的第一個元素。

+0

感謝您提供清晰明瞭的答案,我可以問您一個後續問題嗎? –

+0

當然,不要問問。 – octachron

+0

感謝您的特權。 假設我有 1) 模塊類型MOD_SIG = SIG的 型噸 VAL分鐘:噸 –