Reputation: 420
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.
Upvotes: 1
Views: 61
Reputation: 27356
Adding something like HasTypeTag
does not have to be repetitious, just have two different traits
and extend TaggedSource
or UntaggedSource
as appropriate.
import scala.reflect.runtime.universe.TypeTag
sealed trait Source
{
def ott: Option[TypeTag[_]]
}
abstract class TaggedSource[T]()(implicit val tt: TypeTag[T]) extends Source {
def ott = Some(tt)
}
trait UntaggedSource extends Source {
def ott = None
}
// many classes with implicit TypeTag
case class SourceA[T]()(implicit val ev: TypeTag[T]) extends TaggedSource[T]
case class SourceB[T]()(implicit val ev: TypeTag[T]) extends TaggedSource[T]
case class SourceC[T]()(implicit val ev: TypeTag[T]) extends TaggedSource[T]
// a few classes without TypeTag
case class EmptySource() extends UntaggedSource
def retrieveTypeTagFromSource(source: Source): Option[TypeTag[_]] =
source.ott
Upvotes: 1