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

时间:2017-03-09 13:10:58

标签: scala types existential-type

使用以下类层次结构:

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()的返回类型为Seq[Any],这对我来说似乎不对,因为它是RefinedProvider,所以{{1}应该返回get()

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

Seq[_ <: HasX]

2 个答案:

答案 0 :(得分:1)

故障单SI-2385表明这只是将A[_]解释为A[T] forSome { type T >: Nothing <: Any }的规范的一部分,如果可能的话,不会推断出更严格的界限。人们可能想知道规范是否不应该更新。

票证SI-6169似乎暗示如果推断出更严格的界限,某些事情就会停止工作。我不确定如何以及为什么。

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

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

val provider: RefinedProvider[_ <: HasX]

答案 1 :(得分:0)

这是因为您使用通配符_来声明您的变量类型: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