Предположим, что мы хотим сделать такую функцию, как minBy
, которая возвращает все элементы равного минимализма в коллекции:
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
.
Поэтому я попытался изменить подпись на
def multiMinBy[A, B: Ordering, C <: Traversable[A]](xs: C)(f: A => B)
в надежде, что я могу получить C
назад, а не Traversable[A]
. Однако я ничего не получаю:
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 type parameter bounds [A,B,C <: Traversable[A]]
Я думаю, это потому, что мы имеем C
, появляющийся в аргументах до того, как A
было выведено? Поэтому я перевернул порядок аргументов и добавил листинг:
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]
}
который работает, за исключением того, что мы должны называть его следующим образом:
multiMinBy((x: String) => x.last)(List("zza","zzza","zzb","zzzb"))
Есть ли способ сохранить исходный синтаксис, возвращая правильный тип коллекции?