I am using a map to associate certain values with a tuple (Int, Double) where the int is the order they appeared and the double the number of times they show (it is not, but is clearer like this using int and double to distinguish)
The tricky part is that I want to use different monoids for each element of the tuple, for the int I want to keep the min value, to remember first appearance, while for the double I want to use the addition monoid So for an existing key we have:
val map1 = Map("a" -> (1, 5.0), "b" -> (2, 4.0), "c" -> (3, 8.0))
val map2 = Map("b" -> (4, 1.0))
val merge = map1.toMap |+| map2.toMap
// Map(a -> (1, 5.0), b -> (2, 5.0), c -> (3, 8.0))
And for a new key we have:
val map2 = Map("d" -> (4, 1.0))
val merge2 = map1.toMap |+| map2.toMap
// Map(a -> (1, 5.0), b -> (2, 4.0), c -> (3, 8.0), d -> (4, 1.0))
I can not find a way do this, i can obviously use the addition monoid, and i can use the minval one, but i can not see how to combine them. Any help appreciated! thanks
You can use
scalaz.std.tuple.tuple2Monoid
explicitly with the two monoids you want:And then:
This isn't really ideal, though, since the type
(Int, Double)
can be used to represent lots of different things, and you've just defined a monoid instance that might turn up in places you or your users don't expect. Personally I'd use a case class instead:And then define the instance in the
Count
companion object, either explicitly or via thecountMonoid
above and anIsoSet[Count, (Int, Double)]
.I followed Travis Brown and came with a solution built around the case class, to preven a spillover from the new monoid to every (Int, Double)
It works as expected:
In fact we can check the zero for the monoid:
And it does not work where it should not: