如何从通用方法

时间:2017-11-16 08:53:39

标签: scala generics scala-generics

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

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的子类型)作为输入吗?
  3. Scala 2.12.4

1 个答案:

答案 0 :(得分:3)

您可以使用集合库中最强大但最有争议的功能之一来完成您的要求,即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])的使用。