繁体   English   中英

多态性在scala中没有按预期工作

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM