首页 > 解决方案 > Scala Curried 类型不匹配

问题描述

因此,在我们的教科书中经过反复试验和研究后,我得到了以下功能,我可以想出一个解决方案。

def prodC1(f : Int => Int) : (Int, Int) => Int = {
  def prodA1(a : Int, b : Int) : Int =
    if(a > b) 1 else f(a) * prodA1(a+1, b)
  prodA1 // Why do i need this line here 
}

如果我不说我得到类型不匹配,有人可以详细说明/解释这条线的要求吗?

标签: scalacurrying

解决方案


所以你需要知道很多事情才能真正理解这个问题的答案。

在 Scala 中 anydef是 a method,它只不过是 some 的成员之一objectmethods不是 Scala 中的一等成员,这也意味着它们methods不能单独存在。

在 Scala 中,value任何事物的 of 都必须是expression. 这意味着 a 的 RHSdef需要是一个类似的表达式def abc = some-expression。表达式的示例是1, 1 + 1,"xyz"anotherMethodCallWhichWillReturnAnExpression()

类似的东西def abc = xxxxxx不是expressionScala 语言中的定义。因此你不能这样做,

def prodC1(f : Int => Int) : (Int, Int) => Int = {
  def prodA1(a : Int, b : Int) : Int =
    if(a > b) 1 else f(a) * prodA1(a+1, b)
}

现在,当您添加额外的行时prodA1,您是在告诉 Scala 返回prodA1您刚刚定义的 this。但是记住prodA1只是一个method,因此不能单独存在,因此实际上不能返回。

但是functions是 Scala 中的第一类成员(表示为各种类之一的实例FunctionX),因此可以返回。

在这种情况下,Scala 将智能地将其提升method为 a functionof type (Int, Int) => Int。这称为 eta 扩展。

更详细地了解事情。您可以打开 Scala 控制台并尝试以下操作。

scala> val s = "abc"
// s: String = abc

scala> val i = 10
// i: Int = 10


scala> def prodA1(a : Int, b : Int) : Int = if (a > b) 1 else a * prodA1(a+1, b)
// prodA1: (a: Int, b: Int)Int

注意 Scala 控制台的实际输出valuesdef. 现在,如果我尝试使用prodA1as valueval我会收到以下错误。

scala> val x = prodA1
// <console>:12: error: missing argument list for method prodA1
// Unapplied methods are only converted to functions when a function type is expected.
// You can make this conversion explicit by writing `prodA1 _` or `prodA1(_,_)` instead of `prodA1`.
//        val x = prodA1

Scala 告诉您,您method可以function使用_. 让我们试试。

scala> val x = prodA1 _
// x: (Int, Int) => Int = $$Lambda$1077/293669143@13278a41

现在x是一个function类型(Int, Int) => Int

此外,第一行Unapplied methods are only converted to functions when a function type is expected.告诉您您的案件实际发生了什么。

由于prodC1预计会返回 afunction类型(Int, Int) => Int并且您提供了prodA1,因此 Scala 曾经eta-expansion自动将您转换methodfunction.


推荐阅读