给定 Scala 中 return 函数的其他替代方法,柯里化的目的是什么?

What's the purpose of Currying given other alternatives to return a function in Scala?

我目前正在学习 Scala 课程,最近我了解到 returning 函数的不同技术。

例如,给定这个函数和方法:

val simpleAddFunction = (x: Int, y: Int) => x + y
def simpleAddMethod(x: Int, y: Int) = x + y

我可以 return 另一个函数就是这样做的:

val add7_v1 = (x: Int) => simpleAddFunction(x, 7)
val add7_v2 = simpleAddFunction(_: Int, 7)
val add7_v3 = (x: Int) => simpleAddMethod(x, 7)
val add7_v4 = simpleAddMethod(_: Int, 7)

所有的值add7_x完成同样的事情,那么柯里化的目的是什么? 如果上述所有功能都具有相似的功能,为什么我必须写 def simpleCurryMethod(x: Int)(y: Int) = x + y

就是这样!我是函数式编程的新手,除了通过减少重复使用参数来节省时间之外,我不知道 Currying 的很多用例。因此,如果有人能向我解释柯里化相对于前面的示例或一般柯里化的优势,我将不胜感激。

就这样,祝你有个愉快的一天!

Scala 2 中,柯里化方法只有四个实用的理由 (据我所知,如果有人有另一个有效的用例,那么请让我知道).

  1. (可能是使用它的主要原因) 来驱动类型推断。

例如,当您想要接受一个函数或另一种泛型值时,其泛型类型应该从一些普通数据中推断出来。例如:

def applyTwice[A](a: A)(f: A => A): A = f(f(a))

applyTwice(10)(_ + 1) // Here the compiler is able to infer that f is Int => Int

在上面的例子中,如果我不柯里化函数,那么我需要做类似的事情:applyTwice(10, (x: Int) => x + 1) 来调用函数。
这是多余的,看起来更糟 (恕我直言).

Note: In Scala 3 type inference is improved thus this reason is not longer valid there.

  1. (这可能是现在 Scala 3 的主要原因) 调用者的用户体验。

例如,如果您希望一个参数是一个函数或一个块,它通常最好作为它自己的 (和最后一个) 参数列表中的单个参数,这样它看起来很好用。例如:

def iterN(n: Int)(body: => Unit): Unit =
  if (n > 0) {
    body
    iterN(n - 1)(body)
  }

iterN(3) {
  println("Hello")
  // more code
  println("World")
}

再一次,如果我不柯里化之前的方法,用法将是这样的:

iterN(3, {
  println("Hello")
  // more code
  println("World")
})

哪个看起来不太好:)

  1. (根据我的经验,这很奇怪但有效) 当您知道大多数用户会部分调用它时 return 一个函数。

因为 val baz = foo(bar) _ 看起来比 val baz = foo(bar, _) 好,而且对于第一个,你有时不会像这样使用下划线:data.map(foo(bar))

Note: Disclaimer, I personally think that if this is the case, is better to just return a function right away instead of currying.


编辑

感谢@jwvh 指出这第四个用例。

  1. (在使用依赖路径的类型时有用)当你需要引用之前的参数时。例如:
trait Foo {
  type I

  def bar(i: I): Baz
}

def run(foo: Foo)(i: foo.I): Baz =
  foo.bar(i)