不变类实例列表的LUB

时间:2016-10-17 19:51:44

标签: scala

给定一个带有covariant类型参数的类:

scala> class G[+A]
defined class G

以下列表显示List[G[Any]]的最小上限。

scala> List(new G[Int], new G[String])
res1: List[G[Any]] = List(G@5aa360ea, G@6548bb7d)

然后,给定一个带有invariant类型参数的类:

scala> class F[A]
defined class F

我看到List[F[_ >: String with Int]]的最小上限(LUB)。

scala> List(new F[Int], new F[String])
res0: List[F[_ >: String with Int]] = List(F@6c4980d3, F@327bcebd)

一个更简单的示例显示了List[Any]的LUB:

scala> List( (42 : Int), "foobar" )
res2: List[Any] = List(42, foobar)

请解释List的{​​{1}}的LUB。

1 个答案:

答案 0 :(得分:2)

G在其类型参数A上是协变。这意味着,对于任何类型AB,如果A是<{1>}的子类型,那么GG[A]子类型。让我们简单地写一下,使用G[B]来表示A <:< BA子类型,然后是B

这意味着当我们有G[A] <:< G[B]时,允许编译器将其推断为List(new G[Int], new G[String]),因为List[Any]List[G[Int]] <:< List[G[Any]](从List[G[String]] <:< List[G[Any]]开始在其类型参数上也是协变的。)

你可能已经知道了,但是对那些还没有的人来说,这是值得解释的。

List对其类型参数F 不变,因此我们无法进行相同的扣除。好的,那么A的类型是什么?由于List(new F[Int], new F[String]) 不变,我们不能说FF[Int] <:< F[Any](因为它不是真的!)。所以它不是F[String] <:< F[Any]

那么编译器可以推断出什么?它唯一真正的选择是一些存在类型,因为它不能是List[F[Any]].,或Any,或其他任何不破坏协方差的东西。由于它正在寻找最小上限,它推断出一个存在类型,它由下面包含类型的复合(在String with Int中)限定。也就是说,F某些无名字型,其下限 _ >: String with Int

或者,换句话说,我们知道我们有String with Int List个,但我们不知道每个类型中包含的是什么类型。只有F中任何给定的FListF[Int],但就是这样。