scr*_*cry 9 ocaml currying named-parameters
试图了解Ocaml的命名参数机制.我理解基础知识,但文档显示了这样的示例:
# let f ~x ~y = x - y;;
val f : x:int -> y:int -> int = <fun>
# let x = 3 and y = 2 in f ~x ~y;;
- : int = 1
Run Code Online (Sandbox Code Playgroud)
在应用中仅使用波浪号时究竟发生了什么?它只是简写~x:x,类似于定义吗?如果是这样,有人可以解释为什么这样:
# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
# let add = (+) and i = 0
in ListLabels.fold_left ~add ~i [1;2;3];;
Run Code Online (Sandbox Code Playgroud)
产生
- : 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 = <fun>
Run Code Online (Sandbox Code Playgroud)
该男子说"请注意像ListLabels.fold_left这样的函数,其结果类型是一个类型变量,永远不会被视为完全应用."
以下是您的示例中发生的情况.要小心它有点牵扯.
# ListLabels.fold_left;;
- : f:('a -> 'b -> 'a) -> init:'a -> 'b list -> 'a = <fun>
Run Code Online (Sandbox Code Playgroud)
只是经典用法:接受ListLabels.fold_left3个参数,即标记的函数f,初始值设定项init和列表.
现在,在
let add = (+) and i = 0
in ListLabels.fold_left ~add ~i [1;2;3];;
Run Code Online (Sandbox Code Playgroud)
该申请ListLabels.fold_left ~add ~i [1;2;3]被认为是不完整的(如该男子所说).这意味着`ListLabels.fold_left首先接收其未命名的参数,[1;2;3]并返回类型的函数f:('a -> int -> 'a) -> init:'a -> 'a.让我们称这个函数为foo.
既然你给了两个命名参数,标记add和i,类型'a推断是一个功能型的类型,add:'c -> ~i:'d -> 'e.
基于该类型的变量 add和i,类型'c必须是int -> int -> int,而且'd必须是int.
替换类型中的那些值'a,我们得出类型'a是add:(int -> int -> int) -> i:int -> 'e.并在foo类型中替换它(我很高兴有复制粘贴;-),它的类型是
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)
Run Code Online (Sandbox Code Playgroud)
删除不必要的括号,和α转换(即重命名)'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
Run Code Online (Sandbox Code Playgroud)
这就是foo的类型.但请记住,你将两个参数传递给foo,标记为~add和~i.所以你在最后得到的价值不是类型,add:(int -> int -> int) -> i:int -> 'a而是类型'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
Run Code Online (Sandbox Code Playgroud)