您可能更喜欢部分应用函数的原因有几个。最明显也可能是肤浅的一点是,你不必写出addOnePA之类的中间函数。
List(1, 2, 3, 4) map (_ + 3) // List(4, 5, 6, 7)
比
好
def add3(x: Int): Int = x + 3
List(1, 2, 3, 4) map add3
相比之下,即使是匿名函数方法(下划线最终被编译器扩展为)也感觉有点笨拙。
List(1, 2, 3, 4) map (x => x + 3)
从表面上看,当您真正将函数作为一等值传递时,部分应用会派上用场。
val fs = List[(Int, Int) => Int](_ + _, _ * _, _ / _)
val on3 = fs map (f => f(_, 3)) // partial application
val allTogether = on3.foldLeft{identity[Int] _}{_ compose _}
allTogether(6) // (6 / 3) * 3 + 3 = 9
想象一下,如果我没有告诉你 fs 中的功能是什么。提出命名函数等价物而不是部分应用程序的技巧变得更难使用。
至于柯里化,柯里化函数通常可以让您自然地表达产生其他函数的函数转换(而不是在末尾简单地产生非函数值的高阶函数),否则可能不太清楚。
例如,
def integrate(f: Double => Double, delta: Double = 0.01)(x: Double): Double = {
val domain = Range.Double(0.0, x, delta)
domain.foldLeft(0.0){case (acc, a) => delta * f(a) + acc
}
可以按照您在微积分中实际学习积分的方式来思考和使用,即作为产生另一个函数的函数的转换。
def square(x: Double): Double = x * x
// Ignoring issues of numerical stability for the moment...
// The underscore is really just a wart that Scala requires to bind it to a val
val cubic = integrate(square) _
val quartic = integrate(cubic) _
val quintic = integrate(quartic) _
// Not *utterly* horrible for a two line numerical integration function
cubic(1) // 0.32835000000000014
quartic(1) // 0.0800415
quintic(1) // 0.015449626499999999
Currying 也缓解了固定函数数量的一些问题。
implicit class LiftedApply[A, B](fOpt: Option[A => B]){
def ap(xOpt: Option[A]): Option[B] = for {
f <- fOpt
x <- xOpt
} yield f(x)
}
def not(x: Boolean): Boolean = !x
def and(x: Boolean)(y: Boolean): Boolean = x && y
def and3(x: Boolean)(y: Boolean)(z: Boolean): Boolean = x && y && z
Some(not _) ap Some(false) // true
Some(and _) ap Some(true) ap Some(true) // true
Some(and3 _) ap Some(true) ap Some(true) ap Some(true) // true
通过使用柯里化函数,我们已经能够“提升”一个函数以在 Option 上处理我们需要的任意数量的参数。如果我们的逻辑函数没有被柯里化,那么我们将不得不有单独的函数来将 A => B 提升到 Option[A] => Option[B]、(A, B) => C 到 (Option[A], Option[B]) => Option[C]、(A, B, C) => D 到 (Option[A], Option[B], Option[C]) => Option[D] 等等。我们关心。
在类型推断方面,柯里化还有其他一些其他好处,如果方法同时具有implicit 和非implicit 参数,则需要使用柯里化。
Finally, the answers to this question 列出更多你可能想要使用柯里化的时间。