Scalaz имеет концепцию полугруппы , которая фиксирует то, что вы хотите здесь сделать, и приводит к, возможно, кратчайшему / чистому решению:
scala> import scalaz._
import scalaz._
scala> import Scalaz._
import Scalaz._
scala> val map1 = Map(1 -> 9 , 2 -> 20)
map1: scala.collection.immutable.Map[Int,Int] = Map(1 -> 9, 2 -> 20)
scala> val map2 = Map(1 -> 100, 3 -> 300)
map2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 100, 3 -> 300)
scala> map1 |+| map2
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 109, 3 -> 300, 2 -> 20)
В частности, двоичный оператор для Map[K, V]
объединяет ключи карт, складывая оператор полугруппы V
по любым повторяющимся значениям. Стандартная полугруппа для Int
использует оператор сложения, поэтому вы получаете сумму значений для каждого повторяющегося ключа.
Редактирование: немного больше деталей по запросу пользователя482745.
Математически полугруппа представляет собой всего лишь набор значений вместе с оператором, который принимает два значения из этого множества и выдает другое значение из этого набора. Таким образом, целые числа при добавлении являются полугруппой, например: оператор +
объединяет два ints для создания другого int.
Вы также можете определить полугруппу по множеству «всех карт с заданным типом ключа и тип значения ", пока вы можете придумать некоторую операцию, которая объединяет две карты для создания новой, которая представляет собой комбинацию двух входов.
Если на обеих картах нет ключей , это тривиально. Если один и тот же ключ существует на обеих картах, нам нужно объединить два значения, к которым привязана клавиша. Хм, разве мы не просто описали оператор, который объединяет два объекта одного типа? Поэтому в Scalaz полугруппа для Map[K, V]
существует тогда и только тогда, когда существует полугруппа для V
- полугруппа V
используется для объединения значений из двух карт, которые назначены одному и тому же ключу.
Так как Int
является типом значения здесь, «столкновение» на клавише 1
разрешается путем целочисленного добавления двух отображаемых значений (поскольку это то, что делает оператор полугруппы Int), следовательно 100 + 9
. Если бы значения были Strings, столкновение привело бы к конкатенации строк двух отображаемых значений (опять же, потому что это то, что делает оператор полугруппы для String).
(И интересно, поскольку конкатенация строк не является коммутативный, т. е. "a" + "b" != "b" + "a"
- результирующая полугрупповая операция также не является. Поэтому map1 |+| map2
отличается от map2 |+| map1
в случае String, но не в случае Int.)