5

我正在阅读一本书,使用 F# 进行函数式编程,它(第 33 页),在高阶函数的声明部分

我们已经看到了像 (+) 和 (<<) 这样的高阶内置函数

并在本节末尾

高阶函数也可以通过在 let 声明中提供如下参数来定义:

let weight ro s = ro * s ** 3.0;;

然而,在我今天早些时候提出的一个问题的底部有一些有用的评论(最初的标题是“我什么时候应该把我的函数写成高阶函数”)似乎对这些例子是否真的更高提出了一些疑问——订单功能。

高阶函数的维基百科定义是:

高阶函数(也称为函数形式、泛函或函子)是至少执行以下操作之一的函数: (i) 将一个或多个函数作为输入;(ii) 输出一个函数。

一方面,我可以看到类似(+)和的函数weight可能被视为高阶函数,因为给定一个参数它们返回一个函数。另一方面,我可以看到它们被正确地视为柯里化函数。我正在学习 F# 作为一个自学项目,并希望将概念弄清楚,因此本网站上的答案和讨论特别有帮助。

我的问题是,这些函数的正确术语是什么,也许更重要的是,人们通常如何使用术语“高阶函数”和“柯里化函数”?

4

2 回答 2

12

我想你可以说curried 函数是一个高阶函数,它返回一个函数作为结果。

柯里化函数是一个类型看起来像a -> b -> c- 的函数,如果你添加括号(它不会改变类型)a -> (b -> c),你可以看到这也是高阶的。

但是,您可以编写高阶但没有柯里化的函数。例如,下面的简单函数接受一些函数f并调用它两次:

let runTwice f = f(); f();

这个函数有一个类型(unit -> unit) -> unit,所以它不是柯里化的(它只需要一些输入并返回单位值),但它是高阶的,因为参数是一个函数。

虽然 like 函数(+)在技术上是高阶的(类型是int -> (int -> int)),但我不认为它们是高阶的好例子,因为您通常不会以高阶方式使用它们(但它偶尔有用)。高阶函数更典型的例子是List.map那些以函数为参数的函数。

于 2013-09-10T14:15:14.340 回答
4

粗略地说,柯里化函数是高阶函数的子集。高阶函数接受函数作为参数或在结果中返回函数。柯里化函数是以柯里化形式编写的多元函数,它接受第一个参数并返回一个接受第二个参数的函数,依此类推。

这就是托马斯上面所说的。但是,我认为这里有一个微妙之处。我不认为所有返回函数的函数都是柯里化的,而且我认为 Tomas 的声明“如果添加括号(不会更改类型)”在 F# 中是不准确的。

具体来说,考虑一个接受参数的函数,具有副作用,然后返回另一个接受另一个参数并返回结果的函数:

let f x =
  printfn "%d" x
  fun y -> x+y

F# 推断类型:

val f : int -> (int -> int)

请注意,我相信它在其中放置了看似多余的括号,这正是因为这些类型之间存在细微差别。

此外,虽然这个函数返回一个函数作为它的结果,但我认为它不符合柯里化函数的条件,因为它有副作用。这不是以柯里化形式重写的多元函数......

于 2013-09-20T23:34:13.313 回答