[英]Polymorphism not working as expected in scala
我在object List
声明了两个方法:
def reduce[A, B >: A](l: List[A])(f: (B, B) => B): B =
reduceLeft(l)(f)
def reduceLeft[A, B >: A](l: List[A])(op: (B, A) => B): B = ???
我从scala.collection.TraversableOnce
类中借用了签名。 (由于教学原因,我正在重新创建自己的课程)。
编译器给我这个错误:
[error] /.../List.scala:159: type mismatch;
[error] found : (B, B) => B
[error] required: (A, A) => A
[error] reduceLeft(l)(f)
[error] ^
我的List类是
final case class ::[A](head: A, tail: List[A]) extends List[A] {
override def isEmpty: Boolean = false
}
sealed trait List[+A] {
def head: A
def tail: List[A]
def isEmpty: Boolean
def ::[B >: A](x: B): List[B] =
datastructures.::(x, this)
}
TraversableOnce
定义怎么能逃脱这个? 是否与我没有将该方法定义为中缀操作有关?
sealed trait List[+A] {
...
def reduce(op: (B,B) => B):B = reduceLeft(op) // e.g.
... //reduceLeft...
}
我已经尝试过TraversableOnce类在中缀中声明特性并且它似乎有效(见下文),但是我仍然很好奇为什么对象定义不起作用。
sealed trait List[+A] {
...
def reduce[B >: A](f: (B, B) => B): B =
self.reduceLeft(f)
def reduceLeft[B >: A](op: (B, A) => B): B = {
if (isEmpty)
throw new UnsupportedOperationException("empty.reduceLeft")
var first = true
var acc: B = 0.asInstanceOf[B]
for (x <- self) {
if (first) {
acc = x
first = false
}
else acc = op(acc, x)
}
acc
}
@tailrec
final def foreach[U](f: A => U): Unit = { f(head); tail.foreach(f); }
...
}
这里是这里发生的事情:当你调用reduceLeft(l)(f)
,你首先调用reduceLeft(l)
,使用l: List[A]
。 由于你的reduceLeft有两个类型参数,但是你没有明确指定它们,到目前为止它只有A
可以使用。 因此,编译器尽可能地推断出类型, 两种类型都使用A
您可以通过将此部分应用程序提取到变量中来查看:
val partiallyApplied: ((A, A) => A) => A = reduceLeft(l)
然后,当您使用f: (B, B) => B
应用第二个参数列表时,类型不匹配。
修复很简单 - 在调用reduceLeft时明确说明类型:
def reduce[A, B >: A](l: List[A])(f: (B, B) => B): B = {
reduceLeft[A, B](l)(f)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.