函数类型 ('a -> 'a) -> int -> 'a -> 'a 和 ('a -> 'a) -> int -> ('a -> 'a) 之间有什么区别?
What is the difference between function type ('a -> 'a) -> int -> 'a -> 'a and ('a -> 'a) -> int -> ('a -> 'a)?
当我写一个 Ocaml 函数来递归地组合同一个函数 n 次时,我是这样做的:
let rec compose f n =
(fun x -> if n = 1 then f x else ((compose f (n-1))) (f x));;
它给出了类型
val compose : ('a -> 'a) -> int -> 'a -> 'a = <fun>
类型有什么区别
('a -> 'a) -> int -> 'a -> 'a
并输入
('a -> 'a) -> int -> ('a -> 'a)
?
对于后一种类型,类似的 compose 函数看起来如何?
它们之间没有区别。但有时库的作者使用括号来表示,计算实际上是分阶段的,因此最好部分地应用它,这样你可以获得更有效的功能,而不是每次都应用它。但是从类型系统的角度来看,这些功能是完全相同的,因为 ->
类型运算符关联到右边。
作为对@ivg 回答的补充,这是我犯的一个错误。考虑这两个具有相同类型 int -> int -> int
的函数。 (;;
添加到顶层粘贴)
let f a b =
let ai =
Printf.printf "incrementing %d to %d\n" a (a + 1);
a + 1 in
b + ai;;
let f' a =
let ai =
Printf.printf "incrementing %d to %d\n" a (a + 1);
a + 1 in
function b -> b + ai;;
如果您部分申请
let f_1 = f 1;;
let f'_1 = f' 1;;
您会看到不同之处。我的想法是 f
做 f'
做的事。实际上,Ocaml 很急切,但 没有 急切地开始在偏函数应用程序中求值,直到用完所有参数。为了指出区别,将 f'
的类型写成 int -> (int -> int)
是有意义的。
当我写一个 Ocaml 函数来递归地组合同一个函数 n 次时,我是这样做的:
let rec compose f n =
(fun x -> if n = 1 then f x else ((compose f (n-1))) (f x));;
它给出了类型
val compose : ('a -> 'a) -> int -> 'a -> 'a = <fun>
类型有什么区别
('a -> 'a) -> int -> 'a -> 'a
并输入
('a -> 'a) -> int -> ('a -> 'a)
?
对于后一种类型,类似的 compose 函数看起来如何?
它们之间没有区别。但有时库的作者使用括号来表示,计算实际上是分阶段的,因此最好部分地应用它,这样你可以获得更有效的功能,而不是每次都应用它。但是从类型系统的角度来看,这些功能是完全相同的,因为 ->
类型运算符关联到右边。
作为对@ivg 回答的补充,这是我犯的一个错误。考虑这两个具有相同类型 int -> int -> int
的函数。 (;;
添加到顶层粘贴)
let f a b =
let ai =
Printf.printf "incrementing %d to %d\n" a (a + 1);
a + 1 in
b + ai;;
let f' a =
let ai =
Printf.printf "incrementing %d to %d\n" a (a + 1);
a + 1 in
function b -> b + ai;;
如果您部分申请
let f_1 = f 1;;
let f'_1 = f' 1;;
您会看到不同之处。我的想法是 f
做 f'
做的事。实际上,Ocaml 很急切,但 没有 急切地开始在偏函数应用程序中求值,直到用完所有参数。为了指出区别,将 f'
的类型写成 int -> (int -> int)
是有意义的。