以下劃線作爲前綴的類型變量告訴我們該變量是弱多態性。弱多態變量只能用於一種類型,但編譯器無法推導出確切的類型,因此類型變量帶有下劃線標記。
當您第一次提供參數時,變量將不再是多態,並且將只能接受單一類型的參數。
通常情況下,函數不是泛化的,但如果它的可能包含可變狀態,則標記爲弱多態。在你的例子中,這可能是這種情況,因爲類型系統不知道List.fold_left
是純粹還是不純的函數。
編輯: 爲什麼避免局部應用(ETA膨脹)允許函數(偶數不純)是多態性?
讓我們定義一個函數,每次函數調用時都會增加一個內部計數器並將其打印出來。在這一點,它需要一個函數作爲參數,增加後的反抽應用它:
let count f =
let inc = ref 0 in
(fun x -> inc := !inc + 1; print_int !inc; f x);;
此功能是多態的:('a -> 'b) -> 'a -> 'b
。
接下來,讓我們再定義兩個函數。理財一週報多態:
let max' = count max;;
val max' : '_a -> '_a -> '_a = <fun>
和多態之一:
let max'' x = count max x;;
val max'' : 'a -> 'a -> 'a = <fun>
現在請注意打印什麼,當我們執行這些功能:
max' 1 2;; (* prints 1 *)
max' 1 2;; (* prints 2 *)
max' 1 2;; (* prints 3 *)
max'' 1 2;; (* prints 1 *)
max'' 1 2;; (* prints 1 *)
max'' 1 2;; (* prints 1 *)
所以我們設計爲每週多態函數有一個持續可變狀態裏面允許使用計數器的預期,而多態功能是無狀態,並且每次調用都重構,儘管我們想要在裏面有一個可變變量。
。這是一個編譯器更喜歡可與任何單一類型的,而不是支承全面多態性可以使用弱多態函數的原因。
爲什麼在函數定義的末尾添加'l'使其具有強多態性? –
是的,這是價值限制。對於像你這樣的情況,獲得完整多態性的經典方法是「eta擴展」,這正是你在第一個函數中所擁有的。 –
@JeffreyScofield我不明白的是'爲什麼增加一個額外的參數會使它變得強壯'。 –