我正在阅读一本书Functional Programming Using F#,says(第33页),高阶函数声明
部分我们已经看到了高阶内置函数,如(+)和(<<<)
并在本节末尾
也可以通过在let-declaration中提供如下参数来定义高阶函数:
let weight ro s = ro * s ** 3.0;;
然而,在question that I asked earlier today(最初标题为“我应该何时将我的函数编写为高阶函数”)的底部有一些有用的注释,似乎对这些示例是否实际上存在疑问高阶函数。
wikipedia definition of higher-order function是:
高阶函数(也是函数形式,函数或函子)是至少执行以下操作之一的函数:(i)将一个或多个函数作为输入; (ii)输出一个函数。
一方面,我可以看到像(+)
和weight
这样的函数可能被视为高阶函数,因为给定一个参数它们返回一个函数。另一方面,我可以看到它们被恰当地视为咖喱功能。我正在学习F#作为一个自学项目,并希望明确这些概念,因此本网站的答案和讨论特别有用。
我的问题是,这些功能的正确用语是什么,也许更重要的是,人们通常如何使用“高阶函数”和“咖喱函数”这些术语?
答案 0 :(得分:12)
我认为您可以说 curried函数是一个高阶函数,它返回一个函数作为结果。
curried函数是一个类似于a -> b -> c
的函数 - 如果添加括号(不改变类型)a -> (b -> c)
,你可以看到这也是高阶函数
但是,您可以编写高阶但不是咖喱的函数。例如,以下简单函数需要一些函数f
并调用它两次:
let runTwice f = f(); f();
此函数的类型为(unit -> unit) -> unit
,因此它不是curry(它只需要一些输入并返回单位值),但它是高阶的,因为参数是一个函数。
尽管像(+)
这样的函数在技术上是高阶的(类型是int -> (int -> int)
),但我认为它们不是高阶的好例子,因为你通常不会在更高阶的方式(但它偶尔会有用)。更高阶函数的更典型示例是像List.map
这样的函数,它们将函数作为参数。
答案 1 :(得分:5)
粗略地说,curried函数是高阶函数的子集。高阶函数在结果中接受函数作为参数或返回函数。 Curried函数是以curry形式编写的多元函数,作为接受第一个参数的函数,并返回接受第二个参数的函数,等等。
这就是Tomas上面所说的。但是,我认为这里有一个微妙之处。我不认为所有返回函数的函数都是curry,我认为Tomas'声明“如果你添加括号(不改变类型)”在F#中是不准确的。
特别地,考虑一个带参数的函数,有副作用然后返回另一个带另一个参数并返回结果的函数:
let f x =
printfn "%d" x
fun y -> x+y
F#推断类型:
val f : int -> (int -> int)
请注意,它在那里放了看似多余的括号,我相信,正是因为这些类型之间存在细微差别。
此外,虽然这个函数返回一个函数作为结果,但我不认为它因为副作用而有资格作为curried函数。这不是以咖喱形式重写的多元函数......