scala - Why there is no Semigroup instance for TrieMap in scalaz -
while can do
map("a" -> 1) |+| map("a" -> 2)
it seems there no support
triemap("a" -> 1) |+| triemap("a" -> 2)
why ?
scalaz
doesn't provide every possible type+operation combination form semigroup, can implement it, instance following implicit
:
import scala.collection.concurrent.triemap import scalaz._, scalaz._ implicit def triemapsemigroup[k: buildkeyconstraint, v: semigroup]: semigroup[triemap[k, v]] = new semigroup[triemap[k, v]] { def append(m1: triemap[k, v], m2: => triemap[k, v]) = (m1 /: m2) { case (res, (k, v)) => res += (k -> res.get(k).cata(semigroup[v].append(_, v), v)) } }
that gives expected:
scala> triemap("a" -> 1) |+| triemap("a" -> 2) res: triemap(a -> 3)
of course work every value semigroup has been defined in scalaz
.
what monoid?
if want optimised version of implicit
works monoid too:
implicit def triemapmonoid[k: buildkeyconstraint, v: semigroup]: monoid[triemap[k, v]] = new monoid[triemap[k, v]] { def 0 = triemap.empty[k, v] def append(m1: triemap[k, v], m2: => triemap[k, v]) = { val m2instance: triemap[k, v] = m2 val (from, to, semigroup) = { if (m1.size > m2instance.size) (m2instance, m1, semigroup[v].append(_: v, _: v)) else (m1, m2instance, (semigroup[v].append(_: v, _: v)).flip) } from.foldleft(to) { case (res, (k, v)) => res += (k -> res.get(k).map(semigroup(_, v)).getorelse(v)) } } }
(code shameless adapted scalaz/std/map.scala
)
Comments
Post a Comment