How to determine whether a type parameter is a subtype of a trait?
scala
Solution
This can be achieved with TypeTags (at least 2.10M7):
scala> class Foo; trait Bar
defined class Foo
defined trait Bar
scala> import reflect.runtime.universe._
import reflect.runtime.universe._
scala> def isBar[A <: Foo : TypeTag] = typeOf[A].baseClasses.contains(typeOf[Bar].typeSymbol)
isBar: [A <: Foo](implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean
scala> isBar[Foo]
res43: Boolean = false
scala> isBar[Foo with Bar]
res44: Boolean = true
TypeTags provide a 1:1 translation of Scala types because they represent the types the compiler knows. Therefore they are much more powerful than plain old Manifests:
scala> val fooBar = typeTag[Foo with Bar]
fooBar: reflect.runtime.universe.TypeTag[Foo with Bar] = TypeTag[Foo with Bar]
With the method `tpe` we get full access to Scalas new Reflection:
scala> val tpe = fooBar.tpe // equivalent to typeOf[Foo with Bar]
tpe: reflect.runtime.universe.Type = Foo with Bar
scala> val tpe.<tab><tab> // lot of nice methods here
=:= asInstanceOf asSeenFrom baseClasses baseType contains declaration
declarations erasure exists find foreach isInstanceOf kind
map member members narrow normalize substituteSymbols substituteTypes
takesTypeArgs termSymbol toString typeConstructor typeSymbol widen
Problem
Let's say I have the following types ``` class Foo trait Bar ``` Is there a way to make a method which takes in a Type parameter, T, and determine if that T is a Bar? For example, ``` def isBar[T <: Foo: Manifest] = classOf[Bar].isAssignableFrom(manifest[T].erasure) ``` Sadly, `isBar[Foo with Bar]` is `false` because erasure seems to erase mixins. Also, `manifest[Foo with Bar] <:< manifest[Bar]` is false Is this possible at all? I looked at this question: How to tell if a Scala reified type extends a certain parent class? but that answer doesn't work with mixed-in traits as they seem to be erased as evidenced above.