Scalaz ma koncepcję półgrupy, która przechwytuje to, co chcesz tutaj zrobić, i prowadzi do prawdopodobnie najkrótszego / najczystszego rozwiązania:
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)
W szczególności, operator binarny for Map[K, V]łączy klucze map, Vzawijając operator półgrupy nad zduplikowanymi wartościami. Standardowa półgrupa dla Intużywa operatora dodawania, więc otrzymujesz sumę wartości dla każdego zduplikowanego klucza.
Edycja : trochę więcej szczegółów, zgodnie z prośbą użytkownika482745.
Matematycznie półgrupa to po prostu zbiór wartości wraz z operatorem, który pobiera dwie wartości z tego zbioru i tworzy inną wartość z tego zbioru. Na przykład liczby całkowite są półgrupą - +operator łączy dwie liczby całkowite, aby utworzyć kolejną liczbę int.
Możesz także zdefiniowaćpółgrupę na zbiorze "wszystkich map z podanym typem klucza i typem wartości", o ile możesz wymyślić jakąś operację, która łączy dwie mapy w celu utworzenia nowej, która jest w jakiś sposób połączeniem tych dwóch wejścia.
Jeśli nie ma kluczy, które pojawiają się na obu mapach, jest to trywialne. Jeśli ten sam klucz istnieje w obu mapach, musimy połączyć dwie wartości, na które mapuje klucz. Hmm, czy nie opisaliśmy właśnie operatora, który łączy dwie jednostki tego samego typu? Dlatego w Scalaz półgrupa for Map[K, V]istnieje wtedy i tylko wtedy, gdy półgrupa dla Vistnieje - Vjest używana do łączenia wartości z dwóch map, które są przypisane do tego samego klucza.
Tak więc, ponieważ Intjest to typ wartości, "kolizja" 1klucza jest rozwiązywana przez dodanie liczb całkowitych dwóch odwzorowanych wartości (tak jak robi to operator półgrupy Int) 100 + 9. Gdyby wartości były ciągami, kolizja spowodowałaby konkatenację ciągów dwóch odwzorowanych wartości (ponownie, ponieważ tak robi operator półgrupy dla ciągu).
(Co ciekawe, ponieważ konkatenacja ciągów nie jest przemienna - to znaczy "a" + "b" != "b" + "a"- wynikowa operacja półgrupowa też nie jest. Więc map1 |+| map2różni się od map2 |+| map1przypadku String, ale nie w przypadku Int).
map1 ++ map2