首页 > 解决方案 > Scala按类型参数过滤并返回构造返回类型与类型构造函数

问题描述

我有以下工作代码

case class FilterType[A](t: GenTraversable[A]) {
  def filterType[B](implicit tag: ClassTag[B]): GenTraversable[B] = t.flatMap {
    case element: B => Some(element)
    case _          => None
  }
}

有了这个定义,我可以按预期过滤以下内容

trait Demo
case class Demo1(a: String) extends Demo
case class Demo2(a: Int)    extends Demo

val input: Seq[Demo]              = Seq(Demo1("hello"), Demo2(2))
val output: GenTraversable[Demo1] = FilterType(input).filterType[Demo1]

我想对此进行改进,并将类型构造函数也作为参数,这样我就可以返回与(在本例中为 a )GenTraversable相同的类型,而不是返回 a 。我的尝试如下inputSeq

case class FilterType2[T[_]: GenTraversable, A](t: T[A]) {
  def filterType[B](implicit tag: ClassTag[B]): T[B] = t.flatMap {
    case element: B => Some(element)
    case _          => None
  }
}

但是我收到以下编译错误:

Error 1: type T takes type parameters
Error 2: value flatMap is not a member of type parameter T[A]

标签: scala

解决方案


对于您的第一个错误:

GenTrasversable不是上下文/类型类。您期望的是 的子类GenTrasversable,而不是其上下文,因此您应该使用<:而不是:.

对于您的第二个错误:

flatMap不属于GenTrasversable。它属于GenTraversableLikedoc

工作代码:

您还需要CanBuildFrom在 Scala 2.12 中构建通用集合。

case class FilterType[T[A] <: GenTraversableLike[A, T[A]], A](t: T[A]) {
  def filterType[B](implicit tag: ClassTag[B], bf: CanBuildFrom[T[A], B, T[B]]): T[B] = t.flatMap {
    case element: B => Some(element)
    case _          => None
  }
}

完整代码:代码


推荐阅读