我正在学习类型方差的概念和Scala中的界限以及如何使用它们。我在堆栈溢出上遇到了以下问题,其中一种解决方案提到了如何防止Scala概括类型。
协变量类型参数
以下是解决方案中发布的代码。在以下代码中,添加新类型参数C的帮助?我了解B如何受到约束(作为A和果实亚型的超级型(。但是我对C在这里做什么完全失去了。为什么应该是A的超级类型A。为什么隐式证据要求B为C?
的亚型以及为什么添加橙色物体列表的果实不是香蕉亚型时存在无关的错误。有人可以解释一下吗?
我猜想满足第一个约束,将橙色物体推断为水果物体,但之后就迷失了为什么它说水果不是香蕉的亚型。
case class Banana() extends Fruit
defined class Banana
case class Orange() extends Fruit
defined class Orange
case class Basket[+A <: Fruit](items: List[A]) {
// ...
def addAll[B >: A <: Fruit, C >: A](newItems: List[B])(implicit ev: B <:< C): Basket[B] =
new Basket(items ++ newItems)
// ...
}
defined class Basket
val bananaBasket: Basket[Banana] = Basket(List(Banana(), Banana()))
bananaBasket: Basket[Banana] = Basket(List(Banana(), Banana()))
bananaBasket.addAll(List(Orange())) // not accepted
Main.scala:593: Cannot prove that Product with Serializable with cmd27.Fruit <:< cmd47.Banana.
bananaBasket.addAll(List(Orange()))
语法
def foo[A >: LA <: UA, B...](...)(implicit ev: F[A, B] <:< G[A, B], ...)
表示
- 首先应推断
A, B ...
,以便满足条件A >: LA <: UA, B...
并 - 第二,应检查这些推断的
A, B ...
条件F[A, B] <:< G[A, B], ...
。
基本上是C >: A
和ev: B <:< C
平均值(因为C
无处可使用,并且编译器正在寻找C
为CC_9的最低上限(,为此,我们应该检查B <:< A
。只是我们无法删除C >: A
并用ev: B <:< A
替换CC_14,从那以后我们将拥有Error: covariant type A occurs in contravariant position in type B <:< A of value ev
。
因此,我们希望推断B
,以便B >: A <: Fruit
(即B
应该是 supertype of A
(,对于此B
,请检查B <:< A
(即B
是 subtype 。因此,只有在A = B
时才能满足。这可以防止bananaBasket.addAll(List(Orange()))
编译。