【问题标题】:Avoiding instance of to filter by type避免按类型过滤的实例
【发布时间】:2020-12-29 06:58:57
【问题描述】:

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

有没有一种方法可以安全地实现它? typemembers 对这样的任务有用吗?或者shapeless 可以用于这个任务?

【问题讨论】:

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


    【解决方案1】:

    我想出了两个与 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
    

    【讨论】:

    • 看起来很适合用例,但在未知类型的情况下,我认为asInstanceOf 并不像起初看起来那么糟糕......
    • @SomeName 正确,如果类型未知,无形版本将不起作用。这是任何无形解决方案的典型特征。
    猜你喜欢
    • 2020-12-29
    • 2014-09-01
    • 2015-11-01
    • 2015-12-09
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多