user1473794
user1473794

Reputation: 23

Scala combining maps while handling collision with custom type with Scalaz semigroup

    case class Special(foo: Bar) {

    }
    case class SpecialMap(bar: Map[SpecialKey, Special]) {
           //I want to be able to do
           def combineValuesMap(that: SpecialMap) : SpecialMap = {
               this.bar |+| that.bar
           }
    }

I have tried overloading + in special however that did not enable me to perform. How can I create a special type that will allow me to utilize the semigroup to do this?

Reference for |+| : Best way to merge two maps and sum the values of same key?

Upvotes: 1

Views: 183

Answers (1)

Travis Brown
Travis Brown

Reputation: 139038

You'll need to provide a semigroup instance for your Special type. The "best" place for instances like this is the companion object for the type, since instances defined there will automatically be available:

case class Special(foo: String)

object Special {
  import scalaz.Semigroup

  implicit val semigroupSpecial: Semigroup[Special] = Semigroup.instance(
    (specialA, specialB) => Special(s"(${specialA.foo}-${specialB.foo})")
  )
}

(Note that I'm simplifying a bit, but the idea will be the same in your case.)

And then:

import scalaz.std.map._, scalaz.syntax.semigroup._

val m1 = Map("a" -> Special("a"), "b" -> Special("b"))
val m2 = Map("c" -> Special("c"), "b" -> Special("another b"))
val m3 = m1 |+| m2

This will use the combination function you've provided to combine values in the case of a collision:

scala> m3.foreach(println)
(c,Special(c))
(b,Special((b-another b)))
(a,Special(a))

Which is what you want.

Upvotes: 1

Related Questions