Can an existentially quantified type variable be forced to have only a single type?

前端 未结 2 1829
南方客
南方客 2021-01-13 11:54

Consider the following code

trait Foo[T] {
  def one: Foo[_ >: T]
  def two: T
  def three(x: T)
}

def test[T](f: Foo[T]) = {
  val b = f.one
  b.three(b         


        
2条回答
  •  别那么骄傲
    2021-01-13 12:41

    The problem is the compiler thinks that

    b.two: _>:T
    b.three(_>:T)
    

    i.e. two is a supertype of T and three requires a supertype of T. But a supertype of T is not necessarily assignment compatible with another supertype of T, as in this example:

    A >: B >: C
    def get:A
    def put(B)
    put(get) // type mismatch
    

    So if all the information we have is that they are supertypes of T then we cannot do this safely. We have to explicitly tell the compiler that they are the same supertype of T.

    trait Foo[T] {
      type U <: T
      def one: Foo[U]
      def two: T
      def three(x: T)
    }
    

    Then just set U when you implement the trait:

    val x = new Foo[Dog]{
      type U = Mammal
      ...
    

    I would prefer this approach over the existential types due to the cleaner syntax and the fact that this is core Scala and does not need the feature to be imported.

提交回复
热议问题