dire che vogliamo fare una funzione come minBy
che restituisce tutti gli elementi di uguale minimalismo in una collezione:Tornando tipo di raccolta originale metodo generico
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)
Fin qui, tutto bene, solo che abbiamo un Traversable
indietro invece del nostro List
iniziale.
Così ho provato a cambiare la firma per
def multiMinBy[A, B: Ordering, C <: Traversable[A]](xs: C)(f: A => B)
nella speranza che potrei ottenere un C
indietro piuttosto che un Traversable[A]
. Tuttavia, non ho ricevuto nulla in cambio:
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]]
Credo che questo è perché abbiamo C
che appaiono nelle argomentazioni prima di A
è stato dedotto? Così ho capovolto l'ordine degli argomenti, e ha aggiunto un 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]
}
che funziona, tranne che dobbiamo chiamare in questo modo:
multiMinBy((x: String) => x.last)(List("zza","zzza","zzb","zzzb"))
c'è un modo per mantenere la sintassi originale, ottenendo il giusto tipo di collezione?
Sì, sono d'accordo, questa è una soluzione migliore della mia. –