It's because of type erasure.
During compilation there is a warning
abstract type pattern X.this.T is unchecked since it is eliminated by erasure
Try
import shapeless.TypeCase
trait X {
type T
val OfTypeT: TypeCase[T] // abstract val, not def
def handle: PartialFunction[Any, Unit] = {
case OfTypeT(in) =>
println(s"is a T, $in")
case m =>
print(s"not a T, $m")
}
}
class X1 extends X {
override type T = A
override val OfTypeT = TypeCase[A]
}
val x1 = new X1()
x1.handle(B()) // not a T, B()
See Ways to pattern match generic types in Scala https://gist.github.com/jkpl/5279ee05cca8cc1ec452fc26ace5b68b (another copy of a blog post: http://web.archive.org/web/20171013214913/http://www.cakesolutions.net/teamblogs/ways-to-pattern-match-generic-types-in-scala)
If T
were a type parameter rather than type member we could use a context bound instead of overriding
import shapeless.{TypeCase, Typeable}
abstract class X[T: Typeable] {
private val OfTypeT = TypeCase[T]
def handle: PartialFunction[Any, Unit] = {
case OfTypeT(in) =>
println(s"is a T, $in")
case m =>
print(s"not a T, $m")
}
}
class X1 extends X[A]
val x1 = new X1()
x1.handle(B()) // not a T, B()
Or we could use TypeTag
import scala.reflect.runtime.universe.{TypeTag, typeOf, Type}
def getType[T: TypeTag](t: T): Type = typeOf[T]
abstract class X[T: TypeTag] {
def handle: PartialFunction[Any, Unit] = {
case in if typeOf[T] =:= getType(in) =>
println(s"is a T, $in")
case m =>
print(s"not a T, $m")
}
}
class X1 extends X[A]
val x1 = new X1()
x1.handle(B()) // not a T, B()
or ClassTag
import scala.reflect.ClassTag
abstract class X[T: ClassTag] {
def handle: PartialFunction[Any, Unit] = {
case in: T =>
println(s"is a T, $in")
case m =>
print(s"not a T, $m")
}
}
class X1 extends X[A]
val x1 = new X1()
x1.handle(B()) // not a T, B()
in: T
works, and it is probably because at that pointT
is treated as an Any so everything will match. In general, this design feels unsafe. What exactly do you want to solve here? what is the meta-prioblem? If you are open to suggestions we could try to provide a safer design. – Luis Miguel Mejía SuárezT
. – user