我目前有以下(非类型安全)API,我正在尝试以类型安全的方式重新设计:
import cats.instances.list._
import cats.syntax.functorFilter._
sealed trait EnumType
case object A extends EnumType
case object B extends EnumType
case object C extends EnumType
sealed abstract class TypeInfo[T <: EnumType](val enumType: T)
case class Ainfo() extends TypeInfo(A)
case class Ainfo2() extends TypeInfo(A)
case class Binfo() extends TypeInfo(B)
case class Cinfo() extends TypeInfo(C)
//This is the function implemented in a not typesafe way
def filterByEnumType[T <: EnumType: ClassTag](lst: List[TypeInfo[_]]): List[TypeInfo[T]] = {
lst mapFilter { info =>
info.enumType match {
case _: T => Some(info.asInstanceOf[TypeInfo[T]]) //not type safe
case _ => None
}
}
}
filterByEnumType[A.type](List(Ainfo(), Binfo(), Ainfo2(), Cinfo())) //List(Ainfo(), Ainfo2())
有没有一种方法可以安全地实现它?类型成员对于此类任务有用吗?或者可能可以使用 shapeless
来完成此任务?
最佳答案
我想出了两种与 Shapeless 相关的方法。我不确定这两者是否能完全满足您的需求,因为它们依赖于提前了解列表元素的所有类型。
假设你有这个东西:
import shapeless._
import shapeless.ops.hlist._
type HType = TypeInfo[A.type] :: TypeInfo[B.type] :: TypeInfo[A.type] :: TypeInfo[C.type] :: HNil
val hlist: HType = Ainfo() :: Binfo() :: Ainfo2() :: Cinfo() :: HNil
您可以直接在HList
上使用过滤器:
hlist.filter[TypeInfo[A.type]] // Ainfo() :: Ainfo2() :: HNil
如果您想避免在过滤器调用中显式指定 TypeInfo
,您可以修改过滤器函数(但现在您需要提供 HList 类型 - 这可以使用代理来解决类):
def filterByEnumType[T <: EnumType, L <: HList](
list: L
)(implicit filter: Filter[L, TypeInfo[T]]): filter.Out = {
filter.apply(list)
}
filterByEnumType[A.type, HType](hlist) // Ainfo() :: Ainfo2() :: HNil
关于scala - 避免按类型过滤实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63835437/