2015-02-06 65 views
1

說,如果我有以下功能:爲什麼在Ocaml中函數參數不能是多態的?

let rejected f = (f 1, f "hi");; 

它是由類型檢查拒絕,我真的不明白爲什麼類型檢查拒絕。由於f可以是一個多態函數(如id),並且類型檢查器應該允許它。有人可以解釋嗎?

回答

5

這是由於「讓多態性」,又名「prenex多態性」,又名「ML型多態性」。搜索這些條款會給你一些關於這方面的信息。通俗地說,這就是類型推斷是如何工作的,有些觀點你需要停止泛化,並修正你的類型變量。在ML風格的多態中,這是在let級別完成的。結果,let綁定內部的函數應該統一使用,即使用相同的參數。如果這對您是個問題,那麼您可以使用記錄,對象或(也許)該語言的其他功能來克服它。這是從OCaml FAQ摘錄:

如何寫一個多態參數函數? 在ML中,函數的參數 在函數體內不能是多態的; 因此下面的打字:

let f (g : 'a -> 'a) x y = g x, g y 
val f : ('a -> 'a) -> 'a -> 'a -> 'a * 'a = <fun> 

的功能並不像 多態,我們可以期待。不過,在OCaml中,使用一階多態可能是 。爲此,您可以使用 記錄或對象;在記錄的情況下,您需要在函數中使用它之前聲明 類型。其他

let f (o : <g : 'a. 'a -> 'a>) x y = o#g x, o#g y 
type id = { g : 'a. 'a -> 'a; } 
let f r x y = r.g x, r.g y 
+0

兩種方法可以做到這一點:一流的模塊和(我想說的最優雅)GADTs。我會說對象是一個壞主意,因爲它們在製作的組件上較重。 – PatJ 2015-02-06 02:22:01

+0

@PatJ,你能提供一個例子,說明如何用GADT來解決f g x y = g x,g y問題? – ivg 2015-09-30 17:05:47

+0

檢查後發現我錯了,我認爲可以簡單地在GADT定義中聲明一階多態。我仍然認爲這很酷。 – PatJ 2015-10-01 08:25:15

相關問題