scala - 避免按类型过滤实例

标签 scala functional-programming shapeless algebraic-data-types typesafe

我目前有以下(非类型安全)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/

相关文章:

scala - 如何控制 Swagger 为类型生成模型/模式的方式

R 元编程 : pass expression/quosure to function that partially accesses local frame

functional-programming - 如何将多个参数传入 Ramda 组合链?

haskell - 使用 Numerical.Integration.Tanh Sinh 进行 N 维积分

scala - 映射一个无形的 HList 的类型

scala - 如何使用属性和类型类无形的案例类?

scala - 如何与 Seq[Double] 中的先前值进行比较

Scala:参数化中完全限定类名的模式匹配问题

scala - 通过 LiftAll 收集实例

Scala 编译器在使用泛型的方法中显示 "No TypeTag available for T"