为什么柯里化函数的这个函数定义在 Scala 中不起作用?

Why this function definition from a curried function doesn't work in scala?

我正在学习 Odersky 的 scala 函数式编程课程。

scala 中的 currying 函数定义风格是:

def f(arg1)(arg2)....(argn) = E

显示等同于

def f = (arg1 => (arg2 => ...(argn => E)...))

根据课程。

让我困惑的是为什么这个函数定义不起作用?

    def sumOf(f: Int => Int)(a: Int, b: Int): Int = {
      if (a > b) 0 else f(a) + sumOf(f)(a + 1, b)
    }
    // doesn't compile
    def sumOfDouble = sumOf(x => x * 2)

因为这在其他语言中很常见,例如 js:

    const sum = fn => (a, b) => (a > b) ? 0 : fn(a) + sum(fn)(a + 1, b);
    const sumOfDouble = sum(x => x * 2);
    sumOfDouble(1, 10); // => 110

更让我困惑的是:

      def sumbOf =
        (f: Int => Int) =>
          (a: Int, b: Int) =>
            (
                if (a > b) 0 else f(a) + sumbOf(f)(a + 1, b)
            )
      // this works
      def sumOfDouble = sumbOf(x => x * 2)
      sumOfDouble(1, 10) // => 110

那么这里发生了什么,这两种形式的定义似乎并不等同?

如果是,有什么区别?

你的推理是正确的,除了 def 方法不完全等同于函数值:def 是一个方法,而不是 X => Y.[=17 类型的值=]

Scala 编译器确实会将未应用的方法提升为函数值,但只有在需要这样的值时才会这样做。这意味着编译器必须确保此 "conversion to function value" 是您所期望的。只要您提供明确的类型,它就会无缝地发生。例如,这就是您将 sumOf(x => x * 2) 传递给另一个需要 (Int, Int) => Int 的方法的情况。在你声明 sumOfDouble 的情况下,你只需要更明确一点,下面的例子就可以正常工作:

// Explicit lifting into a function value
def sumOfDouble = sumOf(x => x * 2)(_, _)

// Explicit type to "force" the conversion
def sumOfDouble: (Int, Int) => Int = sumOf(x => x * 2) 

// shorthand for the 1st example, but works for any number of parameters
def sumOfDouble = sumOf(x => x * 2) _ 

def sumOfDouble = sumOf(x => x * 2)

在这种情况下,您只将该方法应用于一个参数,但该方法需要两个参数。如果只想应用一个并将其用作匿名函数,则可以将其作为参数传递给高阶函数。参见 modN 函数 here

  def sumOfDouble = sumbOf(x => x * 2)

这是有效的,因为它 returns 一个接受函数的函数和 returns 一个接受两个参数并将该方法应用于这些参数的函数。

在这种情况下,第一种情况是柯里化,而第二种情况与 higher order functions

更密切相关

希望这对您有所帮助。不明白的请回复