【问题标题】:Scala type parameters by declaring the type inside the functionScala 类型参数通过在函数内部声明类型
【发布时间】:2013-11-03 17:25:36
【问题描述】:

我刚开始学习 Scala,来自 Java 背景。我一直在尝试理解函数中的类型参数和类型的推断。这是 Scala 文档中的标准示例:

class Decorator(left: String, right: String) {
  def layout[A](x: A) = left + x.toString() + right
}

object FunTest extends Application {
  def apply(f: Int => String, v: Int) = f(v)
  val decorator = new Decorator("[", "]")
  println(apply(decorator.layout, 7))
}

如果我尝试将类型参数应用于 apply 函数并将 v 保持为强类型,则会发生类型不匹配。为什么这里没有推断出类型?

def apply[B](f: B => String, v: String) = f(v) //Type mismatch
def apply[B](f: B => String, v: B) = f(v)      //Works fine

谢谢

【问题讨论】:

  • 我认为这是因为 B 不是在您定义“应用”时推断出来的,而是在您调用它时推断出来的。 (疯狂猜测)B 没有被实例化是有道理的,因为 f 是未定义的。

标签: function scala type-parameter


【解决方案1】:

让我们看看apply没有它的身体:

 def apply[B](f: B => String, v: String)

上面写着“apply 是一个在类型 B 上参数化的函数(方法),它接受一个从 BString 的函数,以及一个 String”。

B 视为类型变量;它需要在某个时候实例化。这一点不是apply 的声明。就是当 apply 被应用到 ;-)

根据本合同,必须允许这样的使用:

 def g(i: Int): String = "i is " + i

 apply(g, "foo")  // Here the type variable `B` is "instantiated" to the type Int,

但是考虑到你有一个像f(v) 这样的身体,只是替换,我们看到了矛盾:

替换

 f(v)

 g("foo") // can't compile; g takes a B, which is an Int

【讨论】:

  • 很好的解释,谢谢。这是否意味着该错误更像是合同错误,但如果您输入g:(i: String),理论上可以工作?
  • 不,从这个意义上说,这不是合同错误。这是一个编译错误,因为您要求编译器制定一个矛盾的合同。对[B] 进行参数化意味着B 表示的实际类型取决于使用情况,并且此apply 必须处理any g: B => String;这与apply 的实现相矛盾,后者将String 传递给g,后者采用B 不一定是字符串。
猜你喜欢
  • 2015-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-16
  • 1970-01-01
  • 1970-01-01
  • 2019-07-30
相关资源
最近更新 更多