Scalaz ha il concetto di un semigruppo che cattura ciò che vuoi fare qui e porta probabilmente alla soluzione più breve / pulita:
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)
In particolare, l'operatore binario per Map[K, V]
combina le chiavi delle mappe, piegando V
l'operatore del semigruppo su qualsiasi valore duplicato. Il semigruppo standard Int
utilizza l'operatore addizione, in modo da ottenere la somma dei valori per ciascuna chiave duplicata.
modificare : un po 'più di dettaglio, secondo la richiesta dell'utente482745.
Matematicamente un semigruppo è solo un insieme di valori, insieme a un operatore che prende due valori da quell'insieme e produce un altro valore da quell'insieme. Quindi gli interi in aggiunta sono un semigruppo, ad esempio: l' +
operatore combina due in per creare un altro int.
Puoi anche definire un semigruppo sull'insieme di "tutte le mappe con un determinato tipo di chiave e tipo di valore", a condizione che tu possa inventare qualche operazione che combini due mappe per produrne una nuova che sia in qualche modo la combinazione delle due ingressi.
Se non ci sono chiavi che appaiono in entrambe le mappe, questo è banale. Se la stessa chiave esiste in entrambe le mappe, allora dobbiamo combinare i due valori a cui è mappata la chiave. Hmm, non abbiamo appena descritto un operatore che combina due entità dello stesso tipo? Questo è il motivo per cui in Scalaz Map[K, V]
esiste un semigruppo per se e solo se V
esiste un semigruppo per -V
il semigruppo viene utilizzato per combinare i valori di due mappe assegnate alla stessa chiave.
Quindi, poiché qui Int
è il tipo di valore, la "collisione" sulla 1
chiave viene risolta mediante l'aggiunta intera dei due valori mappati (poiché è quello che fa l'operatore del semigruppo di Int), quindi100 + 9
. Se i valori fossero stati String, una collisione avrebbe comportato la concatenazione di stringhe dei due valori mappati (di nuovo, perché è quello che fa l'operatore del semigruppo per String).
(E interessante, perché la concatenazione di stringhe non è commutativa - cioè, "a" + "b" != "b" + "a"
l'operazione del semigruppo risultante non è neanche. Quindi map1 |+| map2
è diversa dal map2 |+| map1
caso String, ma non nel caso Int.)
map1 ++ map2