为什么 scala 需要存在类型来限制泛型绑定?

Why does scala require existential types to restrict a generic bound?

具有以下 class 层次结构:

trait Provider[A] {
  def get(): Seq[A]
}

abstract class ProviderImpl[A] extends Provider[A] {
  final override def get(): Seq[A] = Seq()
}

trait HasX {
  def getX: Int
}

trait RefinedProvider[A <: HasX] extends Provider[A]

class TypedProviderImpl extends ProviderImpl[HasX] with RefinedProvider[HasX]

我希望能够做到这一点:

val provider: RefinedProvider[_] = new TypedProviderImpl()
provider.get() map (_.getX)

但它不起作用,因为 provider.get() 的 return 类型是 Seq[Any] 这对我来说似乎是错误的,因为它是 RefinedProvider,所以 get() 应该 return 一个 Seq[_ <: HasX].

问题:我可以用存在类型解决这个问题,但为什么编译器不能为我强制执行这个问题?

val provider: RefinedProvider[T] forSome { type T <: HasX } = ...

这是因为您使用 通配符: _ 来声明您的变量类型:val provider: RefinedProvider[_]_ 表示 任何类型,你可以这样做:

val provider = new TypedProviderImpl() // the compiler and IDE will auto infer **provider** type

val provider: RefinedProvider[HasX] = new TypedProviderImpl() // explicitly provider type

Ticket SI-2385 表明这只是将 A[_] 解释为 A[T] forSome { type T >: Nothing <: Any } 的规范的一部分,并且尽可能不推断更严格的界限。有人可能想知道规范是否不应该更新。

Ticket SI-6169 似乎表明,如果推断出更严格的界限,某些事情将停止工作。我不确定如何以及为什么。

一个小的妥协是你可以缩短

val provider: RefinedProvider[T] forSome { type T <: HasX }

val provider: RefinedProvider[_ <: HasX]