Я хотел бы написать метод mergeKeys
который группирует значения в Iterable[(K, V)]
по ключам. Например, я мог бы написать:
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)))
}
}
Однако я хотел бы иметь возможность использовать любой Monoid
вместо того, чтобы писать метод для List
. Например, значения могут быть целыми числами, и я хочу их суммировать, а не добавлять в список. Или это могут быть кортежи (String, Int)
, где я хочу собрать строки в набор, но добавить целые числа. Как я могу написать такой метод? Или есть что-то еще, что я могу использовать в scalaz, чтобы сделать это?
Обновление: я был не так далеко, как думал. Я стал немного ближе, но я все еще не знаю, как заставить его работать, если значения являются кортежами. Нужно ли мне писать еще одно неявное преобразование? То есть одно неявное преобразование для каждого количества параметров типа?
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
}