Der Mann sagt „Vorsicht, dass Funktionen wie ListLabels.fold_left deren Ergebnistyp ist, wird eine Variable vom Typ nie als völlig angewendet betrachtet werden . "
Hier ist, was in Ihrem Beispiel passiert. Vorsicht, es ist ein bisschen beteiligt.
# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
ist nur die klassische Verwendung: ListLabels.fold_left
taks 3 Argumente, nämlich eine Funktion f
, eine initializer init
und eine Liste markiert. Jetzt
, in
let add = (+) and i = 0
in ListLabels.fold_left ~add ~i [1;2;3];;
die Anwendung ListLabels.fold_left ~add ~i [1;2;3]
gilt als unvollständig (wie der Mann sagt). Das bedeutet, dass `ListLabels.fold_left
zuerst das ungedammte Argument [1;2;3]
empfängt und eine Funktion vom Typ f:('a -> int -> 'a) -> init:'a -> 'a
zurückgibt. Nennen wir diese Funktion foo.
Da Sie zwei benannte Argumente geben, etikettiert add
und i
, die Art 'a
wird gefolgert, ein Funktionstyp zu sein, vom Typ add:'c -> ~i:'d -> 'e
.
Basierend auf der Art des Variablenadd
und i
, der Typ 'c
muss int -> int -> int
sein und 'd
muss int
sein.
Ersetzen diese Werte in der Art 'a
, leiten wir, dass der Typ 'a
add:(int -> int -> int) -> i:int -> 'e
ist. Und dies in der Art von foo ersetzen (ich bin froh, dass es kopier Einfügen ;-), seine Art
f:((add:(int -> int -> int) -> i:int -> 'e)
-> int
-> (add:(int -> int -> int) -> i:int -> 'e))
-> init:(add:(int -> int -> int) -> i:int -> 'e)
-> (add:(int -> int -> int) -> i:int -> 'e)
Entfernen unecessary Klammern ist, und Alpha-Umwandlung (dh Umbenennung) 'e
-'a
, erhalten wir
f:((add:(int -> int -> int) -> i:int -> 'a)
-> int
-> add:(int -> int -> int) -> i:int -> 'a)
-> init:(add:(int -> int -> int) -> i:int -> 'a)
-> add:(int -> int -> int) -> i:int -> 'a
das ist die Art von foo ist. Aber denken Sie daran, dass Sie zwei Argumente an foo übergeben, die mit ~add
und ~i
gekennzeichnet sind. Der Wert, den Sie am Ende erhalten, ist nicht vom Typ add:(int -> int -> int) -> i:int -> 'a
, sondern vom Typ 'a
. Und die ganze Art von Ihrem Beispiel ist, wie durch den Compiler zurückgegeben,
f:((add:(int -> int -> int) -> i:int -> 'a)
-> int
-> add:(int -> int -> int) -> i:int -> 'a)
-> init:(add:(int -> int -> int) -> i:int -> 'a)
-> 'a
Wow - was für ein Durcheinander! Es macht aber tatsächlich Sinn, vielen Dank! – scry
Gern geschehen, es war auch schön zu lösen ;-) – jrouquie