简体   繁体   English

为什么List是Semigroup而Seq不是?

[英]Why is List a Semigroup but Seq is not?

I'm fairly new to scalaz and I am trying to figure out why the following code works: 我是scalaz的新手,我试图找出以下代码的工作原理:

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

but this doesn't... 但这不......

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]]()

I see the Map implicit for Semigroup, but I don't see the one for List or Seq. 我看到Semigroup隐含了Map,但我看不到List或Seq的Map。

Couple questions: 情侣问题:

  1. Where is the implicit for ListSemigroup? ListSemigroup隐含在哪里?
  2. Why isn't there one for Seq? 为什么Seq不存在?

So, in Scalaz 7 there's an implicit List to Monoid function which gives you back a Monoid[List[A]] . 因此,在Scalaz 7中有一个隐含的List to Monoid函数 ,它会返回一个Monoid[List[A]] Monoid extends SemiGroup so we have List covered. Monoid扩展了SemiGroup因此我们覆盖了List。

Seq does not get this special treatment. Seq没有得到这种特殊待遇。 There's no implicit conversion from Seq to Monoid or Semigroup . 有从没有隐式转换Seq ,以MonoidSemigroup There is an implicit IndexedSeq to Monoid , but this doesn't help us. Monoid有一个隐含的IndexedSeq ,但这对我们没有帮助。

Why isn't there one for Seq? 为什么Seq不存在? I don't know. 我不知道。 Perhaps Seq violates some laws of monoids/semigroups so there is no conversion. 也许Seq违反了一些幺半群/半群的定律,所以没有转换。 It seems like there were issues with Seq in Scalaz 6 so they've removed some features: https://groups.google.com/forum/?fromgroups=#!searchin/scalaz/Seq/scalaz/Deaec1H11W4/gYFSquXjTzYJ 看起来Scalaz 6中的Seq存在问题,因此他们删除了一些功能: https ://groups.google.com/forum/?fromgroups =#!searchin / skipa / Seq / scalaz / Deaec1H11W4 /gYFSquXjTzYJ

UPDATE UPDATE

Looking at the scala doc it becomes more apparent why the scalaz folks went this way. 看看scala doc,scalaz人们为什么会这样变得更加明显。 List inherits LinearSeq which inherits Seq. List继承继承Seq的LinearSeq。 IndexedSeq inherits Seq. IndexedSeq继承Seq。 If they were to provide a semigroup for Seq, it could override any other semigroup on IndexedSeq or LinearSeq and loose performance advantages between the two. 如果它们为Seq提供半群,它可以覆盖IndexedSeq或LinearSeq上的任何其他半群,并且两者之间的性能优势松散。 If you look at the scalaz signatures for append you can see that they take advantage of these performance differences: 如果您查看附加的scalaz签名,您可以看到它们利用了这些性能差异:

https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/std/List.scala 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 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
  }

If we dig deeper, we see that Seq only implements ++ which has worse performance on lists than ::: for append operations. 如果我们深入挖掘,我们会发现Seq只实现了++ ,它在列表上的性能比:::用于追加操作更差。 So, to answer your second question, performance. 所以,回答你的第二个问题,表现。 If scalaz implemented semigroup for Seq it would most likely lead to ambiguous performance as you would only be able to optimize for indexed. 如果scalaz为Seq实现了semigroup,那么很可能会导致模糊的性能,因为你只能为索引进行优化。 Iterable has the same issue. Iterable也有同样的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM