简化具有特定成员的类型类实例的模式匹配



我有一个框架,它定义了一个类型类,其中大多数实例都具有特定的隐式值:

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

在我的应用程序中,我想使用简单的代码访问上面示例中的ev。以下是我的想法:

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
}

有很多重复,并不理想。我想消除它们,而不仅仅是将重复转移到框架侧(例如,为每个适用的案例类添加HasTypeTag特征(。当模式匹配时,我尝试使用以下行:

case s: {val ev: TypeTag[Any]} => Some(s.ev)

但Scala警告a pattern match on a refinement type is unchecked,所以我不知道这是否真的有效。

添加类似HasTypeTag的内容不必重复,只需具有两个不同的traits,并根据需要扩展TaggedSourceUntaggedSource即可。

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

最新更新