1

Is there an existing Monoid instance for scala.collection.parallel.ParMap in Cats? I don't think so, but I am not certain.

If not, then how would I go about creating such an instance? Here is what I have so far...

import cats._
import implicits._

def parMapMonoid[K, V]: Monoid[ParMap[K, V]] = {
  new Monoid[ParMap[K, V]] {
    def combine(v1: ParMap[K, V], v2: ParMap[K, V]): ParMap[K, V] = {
      ???
    }
    def empty: ParMap[K, V] = {
      ParMap.empty[K, V]
    }
  }
}

...you can assume that there is an appropriate Monoid instance defined for the type V. For the specific use case I have in mine type V=Int.

davidrpugh
  • 4,363
  • 5
  • 32
  • 46

2 Answers2

0

This combines the values pointwise, missing values for a key k are replaced by the identity element of the V-monoid:

def parMapMonoid[K, V](implicit vMon: Monoid[V]): Monoid[ParMap[K, V]] = {
  new Monoid[ParMap[K, V]] {
    def combine(v1: ParMap[K, V], v2: ParMap[K, V]): ParMap[K, V] = {
      val allKeys = v1.keys ++ v2.keys
      (for (k <- allKeys) yield {
        (k, vMon.combine(
          v1.getOrElse(k, vMon.empty),
          v2.getOrElse(k, vMon.empty)
        ))
      })(collection.breakOut)
    }
    def empty: ParMap[K, V] = {
      ParMap.empty[K, V]
    }
  }
}

Since the allKeys is also a parallel collection, the whole construction should still be "reasonably parallelized".

Andrey Tyukin
  • 43,673
  • 4
  • 57
  • 93
-1

If you need to just somehow combine ParMaps then you can just use regular Monoid[Map[_, _]] . No, unfortunately, you can't since ParMap is not a subtype of Map. But if you want to leverage ideomatic FP you should avoid structures like ParMap since they mix description of data and execution model.

simpadjo
  • 3,947
  • 1
  • 13
  • 38
  • I don't understand how one "can just use regular `Monoid[Map[_,_]]`". Can you please elaborate? Good point about need to avoid structures like ParMap when writing idiomatic FP. – davidrpugh Jul 10 '18 at 03:23