gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 08:53:27 25 4
gpt4 key购买 nike

我在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 类中借用了签名。 (出于教学原因,我正在重新创建自己的类(class))。

编译器给了我这个错误:

[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 可以使用。因此,编译器会尽可能地推断类型,both 类型 使用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)
}

关于scala - 多态性在scala中没有按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35824141/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com