11

我有几个与咖喱函数相关的问题。在这里我一一问他们

1) http://twitter.github.com/scala_school/basics.html给出了一个柯里化函数的例子——我认为这是一个函数定义,但实际上不是。REPL 根本不认为这是一个有效的声明。

multiplyThenFilter { m: Int =>   m * 2 } { n: Int =>   n < 5}

2) 为什么我们不能从部分参数化的方法中定义一个函数?即,以下定义有什么问题?

scala> def multiply(m: Int, n: Int): Int = m * n
multiply: (m: Int, n: Int)Int

scala> val timesTwo = multiply(2,_)
<console>:11: error: missing parameter type for expanded function ((x$1) => multiply(2, x$1))
       val timesTwo = multiply(2,_)
                                 ^

3)为什么我们不能使一个部分参数化的函数柯里化?即,以下定义有什么问题?

scala> (multiply(_,_)).curried
  res13: Int => (Int => Int) = <function1>  // THIS IS OK

scala> (multiply(20,_)).curried
<console>:12: error: missing parameter type for expanded function ((x$1) => multiply(20, x$1))
              (multiply(20,_)).curried
                           ^
4

1 回答 1

12

问题 1

Scala School 的例子令人困惑——它绝对不是一个定义。在 GitHub 上存在一个问题,所以可能是一个错误。您可以想象一个合理的定义可能如下所示:

def multiplyThenFilter(f: Int => Int)(p: Int => Boolean): Int => Option[Int] = {
  i =>
    val j = f(i)
    if (p(j)) Some(j) else None
}

(或者,等效地,f andThen (Some(_) filter p)。)

那么该示例将是一个函数,它将其输入加倍并在 a 中返回结果,Some如果它小于 5,None否则返回 a。但在对该问题作出回应之前,没有人确切知道作者的意图。


问题2

timesTwo不起作用的原因只是 Scala 编译器不支持这种类型推断——有关一些相关细节,请参阅这个问题我的回答。您需要使用以下选项之一:

def multiply(m: Int, n: Int): Int = m * n    
val timesTwo = multiply(2, _: Int)

def multiply(m: Int)(n: Int): Int = m * n    
val timesTwo = multiply(2) _

即,如果您想在这里进行类型推断,则需要使用多个参数列表。否则,您必须帮助编译器确定类型。


问题 3

对于您的第三个问题,假设我们有以下内容来避免您的第二个问题中的问题:

val timesTwo = multiply(2, _: Int)

这是 a Function1,只是没有curried方法——你需要 a Function2(或Function3,等等)。

谈论使用单个参数对函数进行柯里化是没有意义的。Currying 接受一个具有多个参数的函数,并为您提供一个接受单个参数的函数,该函数返回另一个函数(它本身可能接受一个参数并返回另一个函数,等等)。

于 2012-06-10T19:23:34.620 回答