I would like to create a union of two maps whose key type is the same and whose value type is a collection of elements, but whose types are different.
Consider the f
Just for the curious, here's how it could be done using Scalaz:
import scalaz._, Scalaz._
case class Child(name: String)
val peopleToChildren = Map(
"max" -> List(Child("a"), Child("b")),
"yaneeve" -> List(Child("y"), Child("d"))
)
case class Pet(name: String)
val peopleToPets = Map(
"max" -> List(Pet("fifi")),
"jill" -> List(Pet("bobo"), Pet("jack"), Pet("Roger rabbit"))
)
val peopleToChildrenAndPets: Map[String, (List[Child], List[Pet])] =
peopleToChildren.strengthR(nil[Pet]) |+| peopleToPets.strengthL(nil[Child])
Explanation:
nil[Pet]
is just an alias for List.empty[Pet]
strengthR
for a given Functor
tuples contained values, so that its parameter is at the right. Here it is equivalent to peopleToChildren.mapValues(v => (v, nil[Pet]))
strengthL
is the same, but element will be added to the left|+|
is an append operator for a given Semigroup
. The one here is derived recursively:
Map[K, V]
, it uses |+|
to combine values of type V
if a given key exists in both Maps. If the value is only present in one of them, it will be retained as is. Here, V = (List[Child], List[Pet])
(A, B)
, it again uses |+|
to combine both A
s and B
s. Here, A = List[Child]
and B = List[Pet]
List
s - for generic Seq
s this operation is not definedResult:
peopleToChildrenAndPets: Map[String, (List[Child], List[Pet])] = Map(
"max" -> (List(Child("a"), Child("b")), List(Pet("fifi"))),
"jill" -> (
List(),
List(Pet("bobo"), Pet("jack"), Pet("Roger rabbit"))
),
"yaneeve" -> (List(Child("y"), Child("d")), List())
)