24

我对 scalaz 相当陌生,我试图弄清楚为什么以下代码有效:

import scalaz._
import Scalaz._
scala> Map[String,List[String]]() |+| Map[String,List[String]]()
res3: scala.collection.immutable.Map[String,List[String]] = Map()

但这并不...

import scalaz._
import Scalaz._
scala> Map[String,Seq[String]]() |+| Map[String,Seq[String]]()
<console>:14: error: value |+| is not a member of      scala.collection.immutable.Map[String,Seq[String]]
          Map[String,Seq[String]]() |+| Map[String,Seq[String]]()

我看到 Semigroup 的 Map 隐含,但我没有看到 List 或 Seq 的映射。

几个问题:

  1. ListSemigroup 的隐含在哪里?
  2. 为什么 Seq 没有​​一个?
4

1 回答 1

29

因此,在 Scalaz 7 中,有一个隐含ListMonoid函数可以返回一个Monoid[List[A]]. Monoid扩展SemiGroup所以我们已经涵盖了列表。

Seq没有得到这种特殊待遇。没有从SeqtoMonoid或的隐式转换Semigroup。有一个隐含IndexedSeq的 toMonoid,但这对我们没有帮助。

为什么 Seq 没有​​一个?我不知道。也许 Seq 违反了幺半群/半群的一些定律,所以没有转换。Scalaz 6 中的 Seq 似乎存在问题,因此他们删除了一些功能: https ://groups.google.com/forum/?fromgroups=#!searchin/scalaz/Seq/scalaz/Deaec1H11W4/gYFSquXjTzYJ

更新

查看 scala 文档,更清楚为什么 scalaz 人会这样。List继承 LinearSeq,LinearSeq 继承 Seq。IndexedSeq继承 Seq。如果他们要为 Seq 提供一个半群,它可能会覆盖 IndexedSeq 或 LinearSeq 上的任何其他半群,并且两者之间的性能优势会松散。如果您查看附加的 scalaz 签名,您会发现它们利用了这些性能差异:

https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/std/List.scala

  implicit def listMonoid[A]: Monoid[List[A]] = new Monoid[List[A]] {
    def append(f1: List[A], f2: => List[A]) = f1 ::: f2
    def zero: List[A] = Nil
  } 

https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/std/IndexedSeq.scala

implicit def ixSqMonoid[A]: Monoid[IxSq[A]] = new Monoid[IxSq[A]] {
    def append(f1: IxSq[A], f2: => IxSq[A]) = f1 ++ f2
    def zero: IxSq[A] = empty
  }

如果我们深入挖掘,我们会发现 Seq 只实现了++,它在列表上的性能比:::用于追加操作更差。所以,回答你的第二个问题,性能。如果 scalaz 为 Seq 实现了 semigroup,它很可能会导致性能不明确,因为您只能针对索引进行优化。可迭代有同样的问题。

于 2013-03-25T21:07:42.093 回答