Группировка значений по ключу с любым моноидом

Я хотел бы написать метод 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
    }
5
задан schmmd 15 March 2012 в 03:18
поделиться