男性は、「結果の型が型変数である ListLabels.fold_left のような関数は、完全に適用されたと見なされないことに注意してください」と述べています。
これがあなたの例で何が起こるかです。少し絡みますのでご注意ください。
# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
は単なる古典的な使用方法です: ListLabels.fold_left
3 つの引数、つまり というラベルの付いた関数f
、初期化子init
、およびリストを受け取ります。
今
let add = (+) and i = 0
in ListLabels.fold_left ~add ~i [1;2;3];;
アプリケーションListLabels.fold_left ~add ~i [1;2;3]
は不完全と見なされます(男性が言うように). つまり、`ListLabels.fold_left
最初に名前のない引数を受け取り、[1;2;3]
type の関数を返しますf:('a -> int -> 'a) -> init:'a -> 'a
。この関数を foo としましょう。
add
とというラベルの付いた 2 つの名前付き引数を指定しているためi
、その型'a
は 型の関数型であると推測されますadd:'c -> ~i:'d -> 'e
。
変数 add
およびi
の型に基づいて、型は である'c
必要がありint -> int -> int
、 である'd
必要がありますint
。
これらの値を type に置き換えると、 typeが'a
であることがわかります。これを foo の型に置き換えると (コピペがあれば嬉しいです ;-)、その型は'a
add:(int -> int -> int) -> i:int -> 'e
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)
不要な括弧を削除し、アルファ変換 (名前の変更)'e
を にすると'a
、次のようになります。
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
それが foo の型です。~add
ただし、とというラベルの付いた 2 つの引数を foo に渡していることに注意してください~i
。したがって、最後に取得する値は typeadd:(int -> int -> int) -> i:int -> 'a
ではなく、実際には type'a
です。そして、あなたの例の全体の型は、コンパイラによって返されるように、
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