我在理解OCaml中高阶函数的函数类型签名时遇到问题。
fun f -> f 3
(int -> a) -> a
我处理这个问题的方式是f 3
部分将int
作为输入并返回函数f
定义的类型,该类型表示为a
。所以真的,fun f
是一种(int->a)
型。但是,(int -> a) ->
a
中最后的a
从何而来?
你的第一个例子是这样的:
fun f -> f 3
我认为您可能会遇到的一个可能的混淆是,您将其视为名为f
的函数的定义。事实并非如此。这是一个表示函数(也称为 lambda)的匿名值。f
表示此匿名函数的参数。
为了使事情更清晰,让我们将函数命名为g
。换句话说,假设我们这样定义g
:
let g = fun f -> f 3
好的,所以g
是一个f
一个参数的函数。这个f
参数显然是一个函数,因为我们看到它被应用于 3。(即,我们看到它以 3 作为参数调用。g
返回什么?当你调用它时,它会返回f
返回的任何内容,对吧?
由于g
是一个函数,因此其类型必须是以下形式:
d -> c
即,它接受d
类型的东西并返回c
类型的东西。从上面的推理中,我们知道d
是一个函数类型,我们也知道这个函数的返回类型也是g
的返回类型。因此,如果d
(更详细地)b -> a
,则完整的g
类型如下所示:
(b -> a) -> a
然而,我们也知道函数参数f
采用 int 参数,因为我们看到它被应用于 3。所以类型b
必须是int
。这为我们提供了以下g
类型:
(int -> a) -> a
我希望这有助于使事情更清晰。
我们可以这样注释匿名函数:
fun (f : int -> 'a) -> (f 3 : 'a)
也就是说,它是一个从f : int -> 'a
到'a
的函数,所以这就是你最后'a
的来源。