Scala 为什么List是半群而Seq不是?

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[

我是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]]()
导入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的隐式映射

两个问题:

  • ListSemigroup的隐式表达式在哪里
  • 为什么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
      }