curried函数(有一个参数)与方法有何不同?

时间:2014-12-21 01:45:32

标签: scala

我很难理解curried函数(有一个参数)与普通方法的区别。我尝试用前者实现后者,但是无法实现。

我的Market特征定义如下:

package market {
  trait Market {
    def getBuyRate(currency: String): Double
    def getSellRate(currency: String): Double
  }
}

我有另一个FakeMarket特征延伸Market,我希望使用currying来实现getBuyRategetSellRate,如下所示:

package market { 
  trait FakeMarket extends Market with Iterable[Double] {
    def getRate(factor: Double)(currency: String): Double = {
      factor * this.iterator.next()
    }
    def getBuyRate = getRate(1) _
    def getSellRate = getRate(1.02) _
  } 
}

最后,我有RandomFakeMarket对象扩展FakeMarket

package market {
  object RandomFakeMarket extends FakeMarket {
    def iterator = new Iterator[Double] {
      def hasNext = true
      def next = 100.0
    }
  }
}

如此定义类型会出错:

<console>:10: error: object creation impossible, since:
it has 2 unimplemented members.
/** As seen from object RandomFakeMarket, the missing signatures are as follows.
 *  For convenience, these are usable as stub implementations.
 */
  def getBuyRate(currency: String): Double = ???
  def getSellRate(currency: String): Double = ???

       object RandomFakeMarket extends FakeMarket {
              ^

这对我来说似乎很奇怪,因为FakeMarket实现了getBuyRategetSellRateString => Double类型的方法。

如果在Market我做过:

,我可以让它工作
getBuyRate: String => Double

为什么这与我最初定义getBuyRate的方式不同?当只有一个论点时,为什么这会有所不同?现在似乎父特质Market必须担心getBuyRate如何实现(正常函数与curried函数)。

1 个答案:

答案 0 :(得分:4)

与currying没那么相关。 def method(p1: String, p2: String): String与scala中的def method: (String, String) => String不等效。方法和函数之间的区别在于方法支持继承,因此他们需要知道方法的输入和输出,由于含糊不清,这种方法并不那么明显:

def get: String => Double可以是String -> Double(统一成员)和() -> String -> Double(解释为函数)。但是在scala中它是Function1[String, Double]() Function1[String, Double],它们的意思是没有输入。不幸的是,def get(): String => Double在这里没有区别(见下面的例子)。

换句话说,方法可能没有scala中的输入参数(因为副作用可能不是纯函数),因此它无法从{{(String)Double推断String => Double 1}}所以你的整个函数成为一个输出参数。例如,您可以在某个子类中执行override def method: (String, String) => String - 这将覆盖没有参数且返回类型为(String, String) => String的方法,但不会使用输入(String, String)覆盖该方法并返回类型String

另一个问题是方法的类型与函数不同,并且可能只通过eta-expansion进行单向转换,因此scala与UAP有点不兼容:

scala> def aaa(b: String): String = "aaa"
aaa: (b: String)String

scala> aaa _
res4: String => String = <function1>

scala> def aaa: String => String = (a: String) => "aa"
aaa: String => String

scala> def aaa()(b: String): String = "aaa"
aaa: ()(b: String)String

scala> def aaa(): String => String = (a: String) => "aa"
aaa: ()String => String

关于方法与功能的更多信息:Difference between method and function in Scala