Vorrei scrivere un metodo mergeKeys
che raggruppa i valori in un Iterable[(K, V)]
mediante le chiavi. Per esempio, ho potuto scrivere:Valori di gruppo con una chiave con qualsiasi Monoid
def mergeKeysList[K, V](iter: Iterable[(K, V)]) = {
iter.foldLeft(Map[K, List[V]]().withDefaultValue(List.empty[V])) {
case (map, (k, v)) =>
map + (k -> (v :: map(k)))
}
}
Tuttavia, mi piacerebbe essere in grado di utilizzare qualsiasi Monoid
invece di scrivere un metodo per List
. Ad esempio, i valori possono essere numeri interi e voglio sommarli anziché aggiungerli in un elenco. Oppure potrebbero essere delle tuple (String, Int)
dove voglio accumulare le stringhe in un set ma aggiungere gli interi. Come posso scrivere un tale metodo? O c'è qualcos'altro che posso usare in scalaz per fare questo?
Aggiornamento: non ero così lontano come pensavo. Mi sono avvicinato un po ', ma non so ancora come farlo funzionare se i valori sono tuple. Devo scrivere ancora un'altra conversione implicita? Vale a dire una conversione implicita per ogni numero di parametri del tipo?
sealed trait SuperTraversable[T, U, F[_]]
extends scalaz.PimpedType[TraversableOnce[(T, F[U])]] {
def mergeKeys(implicit mon: Monoid[F[U]]): Map[T, F[U]] = {
value.foldLeft(Map[T, F[U]]().withDefaultValue(mon.zero)) {
case (map, (k, v)) =>
map + (k -> (map(k) |+| v))
}
}
}
implicit def superTraversable[T, U, F[_]](
as: TraversableOnce[(T, F[U])]
): SuperTraversable[T, U, F] =
new SuperTraversable[T, U, F] {
val value = as
}
Perfetto, grazie! – schmmd