Вы можете явно использовать scalaz.std.tuple.tuple2Monoid
с двумя нужными вам моноидами:
import scalaz.Monoid
implicit val countMonoid: Monoid[(Int, Double)] = scalaz.std.tuple.tuple2Monoid(
Monoid.instance[Int](math.min(_, _), Int.MaxValue),
Monoid.instance[Double](_ + _, 0)
)
А затем:
scala> import scalaz.std.map._, scalaz.syntax.monoid._
import scalaz.std.map._
import scalaz.syntax.monoid._
scala> val map1 = Map("a" -> (1, 5.0), "b" -> (2, 4.0), "c" -> (3, 8.0))
map1: scala.collection.immutable.Map[String,(Int, Double)] = Map(a -> (1,5.0), b -> (2,4.0), c -> (3,8.0))
scala> val map2 = Map("b" -> (4, 1.0))
map2: scala.collection.immutable.Map[String,(Int, Double)] = Map(b -> (4,1.0))
scala> val merge = map1.toMap |+| map2.toMap
merge: scala.collection.immutable.Map[String,(Int, Double)] = Map(a -> (1,5.0), b -> (2,5.0), c -> (3,8.0))
scala> val map2 = Map("d" -> (4, 1.0))
map2: scala.collection.immutable.Map[String,(Int, Double)] = Map(d -> (4,1.0))
scala> val merge2 = map1.toMap |+| map2.toMap
merge2: scala.collection.immutable.Map[String,(Int, Double)] = Map(a -> (1,5.0), b -> (2,4.0), c -> (3,8.0), d -> (4,1.0))
Это не совсем идеально, так как тип(Int, Double)
может использоваться для представления множества разных вещей, и вы только что определили моноидный экземпляр, который может появляться в местах, которые вы или ваши пользователи не ожидаете.Лично я бы вместо этого использовал класс case:
case class Count(order: Int, number: Double)
, а затем определил экземпляр в объекте-компаньоне Count
, либо явно, либо через countMonoid
и выше IsoSet[Count, (Int, Double)]
.