简体   繁体   中英

Scala: Why is an abstract type member equal to a type parameter by =:= not equal in use?

I am starting to embrace abstract type members over type parameters - mainly because they seem to work better with type inference for me. However, I am still struggling to understand how to use them from outside of the types they are defined in. For example, I cannot understand why the following Scala program should not compile:

trait Thing

trait Describer {
  type X<:Thing
  def describe(x:X) = println(x)
}

object Program extends App {

  def print[T <: Thing, D <: Describer]
    (describer: D, thing:T)
    (implicit ev: D#X =:= T) 
    = describer.describe(thing) 

}

Intuitively, I would expect that the requirement D#X =:= T would guarantee that the two types are indeed equal and hence that instances of two could be used interchangeably, but I get this compilation error:

error: type mismatch;
 found   : thing.type (with underlying type T)
 required: describer.X
    = describer.describe(thing)

What have I misunderstood? Is there another way to do what I want to do? Or failing that, is it safe to cast thing to the required type ( describer.X )?

The type of the parameter of describer.describe is actually describer.X and not D#X . Another thing you have to know is that A =:= B also functions as a conversion from A to B but (at least currently) not the other way around. So the following should work.

def print[T <: Thing]
  (describer: Describer, thing: T)
  (implicit ev: T =:= describer.X) 
  = describer.describe(thing) 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM