我有两个ADT结构。
trait Values[_] {}
case class StringV(values: List[String]) extends Values[String]
case class NumberV(values: List[Double]) extends Values[Double]
// and a few more
trait Filter[_] {}
case class StringFilter(values: Set[String]) extends Filter[String]
case class NumberFilter(lower: Double, upper: Double) extends Filter[Double]
// and a few more
给出两个变量
val v: Values[_]
val f: Filter[_]
如何在运行时检查它们是否具有相同的类型,并恢复if 他们不?模式匹配不起作用。
(v, f) match {
case (v: Values[A], f: Filter[A]) forSome { type A } =>
}
蛮力解决方案
def typecheck(v: Values[_], f: Filter[_]):
Option[(Values[A], Filter[A]) forSome { type A }] =
(v, f) match {
case v: StringV => f match {
case f: StringFilter => Some(v, f)
case _ => None
}
case v: NumberV => f match {
case f: NumberFilter => Some(v, f)
case _ => None
}
}
有没有比简单地输入所有内容更好的解决方案?
编辑:
我希望元组(v, f)
符合类型(Values[A], ParamFilterConfig[A]) forSome { type A }
答案 0 :(得分:1)
您可以使用反射API中的typeOf
:
import reflect.runtime.universe._
def valueAndFilter[V: TypeTag, F: TypeTag](v: Values[V], f: Filter[F]) =
if (typeOf[V] =:= typeOf[F]) Some(v, f) else None
valueAndFilter(NumberV(1 :: Nil), NumberFilter(1d, 2d))
// Some((NumberV(List(1.0)),NumberFilter(1.0,2.0)))
valueAndFilter(StringV(Nil), NumberFilter(1d, 2d))
// None
您还可以在编译时通过请求隐式证据来检查Values
和Filter
的类型是否相等。
def valueAndFilter2[V, F](v: Values[V], f: Filter[F])(implicit ev: V =:= F) = (v, f)
valueAndFilter2(NumberV(1 :: Nil), NumberFilter(1d, 2d))
// (NumberV(List(1.0)),NumberFilter(1.0,2.0))
valueAndFilter2(StringV(Nil), NumberFilter(1d, 2d))
// error: Cannot prove that String =:= Double.