[英]Why there is no Semigroup instance for TrieMap in scalaz
雖然我可以做
Map("a" -> 1) |+| Map("a" -> 2)
似乎不支持
TrieMap("a" -> 1) |+| TrieMap("a" -> 2)
為什么呢
Scalaz
並未提供形成Scalaz
所有可能的Type + Operation組合,但是您可以輕松實現它,例如,使用以下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))
}
}
這給了您預期的效果:
scala> TrieMap("a" -> 1) |+| TrieMap("a" -> 2)
res: TrieMap(a -> 3)
當然,這對於在scalaz
定義的半組中的每個值都scalaz
。
如果您還希望implicit
優化版本也可以用作Monoid:
implicit def trieMapMonoid[K: BuildKeyConstraint, V: Semigroup]: Monoid[TrieMap[K, V]] = new Monoid[TrieMap[K, V]] {
def zero = 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))
}
}
}
(從scalaz/std/Map.scala
改編的無恥代碼)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.