2

我有一个通用方法,它应该返回与输入相同类型的集合:

def removeN[A, C <: Seq[A]](s: C, n: Int): C = {
  s.take(n) ++ s.drop(n + 1) // Sample operation
}

但是这段代码无法编译:

错误:(34, 15) 类型不匹配;找到:需要 Seq[A]:C s.take(n) ++ s.drop(n + 1)

  1. C当明确代表时,这怎么可能Seq[A]?这是否意味着这种连接总是返回父类型的实例Seq[A],而不是子类型C?可以重写我的代码以生成类型的集合C吗?
  2. 这是定义返回相同集合类型(在我的情况下是 的子类型Seq)作为一般输入的通用方法的正确方法吗?

斯卡拉 2.12.4

4

1 回答 1

4

您所要求的可以使用集合库中最强大但最有争议的功能之一来完成,即CanBuildFrom. 方法如下:

import scala.language.higherKinds
import scala.collection.generic.CanBuildFrom

def removeN[A, C[A] <: Seq[A]](s: C[A], n: Int)
  (implicit cbf: CanBuildFrom[C[A], A, C[A]]): C[A] = {
  val builder = cbf()
  builder.sizeHint(s.size)
  builder ++= s.take(n)
  builder ++= s.drop(n + 1)
  builder.result()
}

让我们在 REPL 中给它一个转折:

scala> removeN(List(4, 5, 6), 2)
res0: List[Int] = List(4, 5)

scala> removeN(Vector(4, 5, 6), 2)
res1: scala.collection.immutable.Vector[Int] = Vector(4, 5)

它似乎工作。

import scala.language.higherKinds为了避免对更高种类(C[A])使用的警告,需要。

于 2017-11-16T10:00:28.680 回答