在泛型方法中返回原始集合类型 [英] Returning original collection type in generic method
问题描述
假设我们想要创建一个类似于 minBy
的函数,它返回集合中所有相同的极简元素:
Say we want to make a function like minBy
that returns all elements of equal minimalism in a collection:
def multiMinBy[A, B: Ordering](xs: Traversable[A])(f: A => B) = {
val minVal = f(xs minBy f)
xs filter (f(_) == minVal)
}
scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)
res33: Traversable[java.lang.String] = List(zza, zzza)
到目前为止,一切都很好,除了我们返回了一个 Traversable
而不是我们最初的 List
.
So far, so good, except that we have a Traversable
back instead of our initial List
.
所以我尝试将签名更改为
So I tried changing the signature to
def multiMinBy[A, B: Ordering, C <: Traversable[A]](xs: C)(f: A => B)
希望我能得到一个 C
而不是 Traversable[A]
.但是,我没有得到任何回报:
in the hope I might get a C
back rather than a Traversable[A]
. However, I don't get anything back:
scala> multiMinBy(List("zza","zzza","zzb","zzzb"))(_.last)
<console>:9: error: inferred type arguments [Nothing,Nothing,List[java.lang.String]]
do not conform to method multiMinBy's type parameter bounds [A,B,C <: Traversable[A]]
我认为这是因为在推断 A
之前我们在参数中出现了 C
?所以我翻转了参数的顺序,并添加了一个演员表:
I think this is because we have C
appearing in the arguments before A
has been inferred? So I flipped the order of the arguments, and added a cast:
def multiMinBy[A, B: Ordering, C <: Traversable[A]](f: A => B)(xs: C) = {
val minVal = f(xs minBy f)
(xs filter (f(_) == minVal)).asInstanceOf[C]
}
这行得通,但我们必须这样称呼它:
which works, except we have to call it like this:
multiMinBy((x: String) => x.last)(List("zza","zzza","zzb","zzzb"))
有没有办法保留原始语法,同时恢复正确的集合类型?
Is there a way to retain the original syntax, while getting the right collection type back?
推荐答案
我认为 Miles Sabin 的解决方案太复杂了.Scala 的集合已经拥有使其工作所需的机制,只需进行很小的更改:
I think Miles Sabin solution is way too complex. Scala's collection already have the necessary machinery to make it work, with a very small change:
import scala.collection.TraversableLike
def multiMinBy[A, B: Ordering, C <: Traversable[A]]
(xs: C with TraversableLike[A, C])
(f: A => B): C = {
val minVal = f(xs minBy f)
xs filter (f(_) == minVal)
}
这篇关于在泛型方法中返回原始集合类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!