Scala 为什么List是半群而Seq不是?
我是scalaz的新手,我正试图弄明白为什么下面的代码可以工作:Scala 为什么List是半群而Seq不是?,scala,functional-programming,scalaz,scalaz7,Scala,Functional Programming,Scalaz,Scalaz7,我是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[
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]]()
导入scalaz_
进口Scalaz_
scala>Map[String,Seq[String]]()|+| Map[String,Seq[String]]()
:14:错误:值|+|不是scala.collection.immutable.Map[String,Seq[String]的成员
映射[String,Seq[String]]()|+|映射[String,Seq[String]]()
我看到了半群的隐式映射,但没有看到List或Seq的隐式映射
两个问题:
因此,在Scalaz7中,有一个函数返回一个
Monoid[List[a]]
Monoid
扩展了半群
,所以我们已经涵盖了这个列表
Seq
没有得到这种特殊待遇。没有从Seq
到Monoid
或半群的隐式转换。有一个问题,但这对我们没有帮助
为什么Seq没有一个?我不知道。也许Seq违反了幺半群/半群的一些定律,所以没有转换。Scalaz 6中的Seq似乎存在问题,因此他们删除了一些功能:
更新
看看scala文档,scalaz的人为什么会这样做就更明显了。继承LinearSeq,后者继承Seq。继承Seq。如果他们为Seq提供一个半群,它可能会覆盖IndexedSeq或LinearSeq上的任何其他半群,并失去两者之间的性能优势。如果查看append的scalaz签名,您会发现它们利用了以下性能差异:
如果我们深入研究,就会发现Seq只实现了在列表上比在追加操作上性能更差的功能。所以,回答你的第二个问题,性能。如果scalaz为Seq实现了半组,很可能会导致性能不明确,因为您只能针对索引进行优化。Iterable也有同样的问题。您使用的是什么版本?您的标签表明,您询问的是scalaz 7,而指向Semigroup.scala的链接指向master,即6.x。我实际上使用的是7。我会修复我的链接。很好地回答了关于列表中的链接在哪里的问题。似乎所有的iterables至少都应该是半群……如果你看scala文档,Seq是LinearSeq和IndexedSeq的基础,两者都有不同的性能差异。List继承了LinearSeq,所以我可以理解为什么他们必须选择List和IndexedSeq而不是Seq。我来看看是否可以更简洁地更新它。除了这里已经说过的内容,您还可以看看这个示例:它使用同构
从列表
派生Seq
的实例。使用风险自负:根据Jason Zaugg的说法,Seq
的实例是危险的。
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
}
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
}