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)? 
 
    