I have this framework that defines a type class with most instances having a certain implicit value:
import scala.reflect.runtime.universe.TypeTag
sealed trait Source
// many classes with implicit TypeTag
case class SourceA[T]()(implicit val ev: TypeTag[T]) extends Source
case class SourceB[T]()(implicit val ev: TypeTag[T]) extends Source
case class SourceC[T]()(implicit val ev: TypeTag[T]) extends Source
// a few classes without TypeTag
case class EmptySource() extends Source
In my app, I would like to access ev in the above example using simple code. Here's what I've come up with:
def retrieveTypeTagFromSource(source: Source): Option[TypeTag[_]] = source match {
case s: SourceA[_] => Some(s.ev)
case s: SourceB[_] => Some(s.ev)
case s: SourceC[_] => Some(s.ev)
// many more nearly identical lines
// then handling the remaining classes
case s: EmptySource => None
}
There are a lot of repetitions, not ideal. I would like to eliminate them without merely transferring the repetitions to the framework side (e.g. adding a HasTypeTag trait to every applicable case class). I tried using the following line when pattern matching:
case s: {val ev: TypeTag[Any]} => Some(s.ev)
but Scala warns a pattern match on a refinement type is unchecked, so I don't know if that actually works.
Adding something like
HasTypeTagdoes not have to be repetitious, just have two differenttraitsand extendTaggedSourceorUntaggedSourceas appropriate.