方法如何接受(T<:Seq)[A]并返回T [B] - 具有不同类型参数的相同类型的序列?

时间:2012-09-19 18:29:02

标签: scala

我想实现一个方法,该方法接受一个元素类型的序列并返回不同元素类型的序列。我怎样才能这样做,以便返回相同的Sequence子类?

我的方法目前看起来像这样:

def lookerUpper(ids : Seq[String], someOtherInfo : Int) : Seq[UsefulData] = {
    ... retrieve data for each id ...
}

我希望它更通用,因此传入任何类型的(字符串)序列也是返回的(UsefulData)序列。矢量和列表,尤其是,或者我们可以做到的一般。

这可以用Scala的类型系统表达吗? “返回与此参数相同的类型,但使用不同的类型参数。”

1 个答案:

答案 0 :(得分:3)

要获得完整的答案,你应该看看我很长的问题并回答有关构建者的问题(注意:截至2012年9月,Miles的替代版本在2.9或最新的2.10中都不起作用。)

这是一个让你入门的框架(请注意显式和隐式参数块的奇怪格式,以避免在SO上显示过长的行):

import collection.generic.CanBuildFrom

case class UsefulData(data: Int) {}

def lookerUpper[C[String]](
  ids: C[String], someOtherInfo: Int
)(
  implicit cbf: CanBuildFrom[C[String],UsefulData,C[UsefulData]],
  ev: C[String] => Iterable[String]
): C[UsefulData] = {
  val b = cbf()
  val i = ev(ids)
  i.foreach{ s => b += UsefulData(s.length + someOtherInfo) }
  b.result 
}

并观察它是否有效:

scala> lookerUpper(Vector("salmon","cod"),2)
res0: scala.collection.immutable.Vector[UsefulData] = 
  Vector(UsefulData(8), UsefulData(5))

scala> lookerUpper(Array("salmon","cod"),2)
res1: Array[UsefulData] = 
  Array(UsefulData(8), UsefulData(5))

编辑:如果您只关心TraversableLike的子类(Array不是),并且您将使用标准集合操作来完成所有工作,那么您可以使用{{ 3}}正如路易吉指出的那样。 (也许我应该把这个答案作为另一种观点移到那里。)