为什么列出一个半群但Seq不是? [英] Why is List a Semigroup but Seq is not?
问题描述
我对scalaz相当陌生,我试图找出为什么下面的代码有效:
import scalaz。 _
导入Scalaz._
scala> Map [String,List [String]]()| + | Map [String,List [String]]()
res3:scala.collection.immutable.Map [String,List [String]] = Map()
但这不... ...
import scalaz。 _
导入Scalaz._
scala> Map [String,Seq [String]]()| + | Map [String,Seq [String]]()
< console>:14:error:value | + |不是scala.collection.immutable.Map的成员[String,Seq [String]]
Map [String,Seq [String]]()| + | Map [String,Seq [String]]()
我看到半隐式的Map,对于List或Seq没有看到。
几个问题:
- ListSemigroup的隐式内容在哪里?
- 为什么Seq中没有一个?
因此,在Scalaz 7中有一个 implicit List to
它给你一个 Monoid
function Monoid [List [A]]
。 Monoid
扩展 SemiGroup
,所以我们有List。
Seq
没有得到这种特殊待遇。没有从 Seq
到 Monoid
或 Semigroup
的隐式转换。有一个 implicit IndexedSeq
to Monoid
,但这对我们没有帮助。
为什么Seq没有一个?我不知道。也许Seq违反了单音/半群的一些规律,所以没有转换。似乎在Scalaz 6中Seq存在问题,因此他们删除了一些功能:
https://groups.google.com/forum/?fromgroups=#!searchin/scalaz/Seq/scalaz/Deaec1H11W4/gYFSquXjTzYJ
UPDATE
查看scala文档,它变得更加明显,为什么scalaz人会这样做。 列表继承继承Seq的LinearSeq 。 IndexedSeq 继承了Seq。如果他们要为Seq提供一个半群,它可以覆盖IndexedSeq或LinearSeq上的任何其他半群,并且两者之间的性能优势将会减弱。如果你看看scalaz签名的追加,你可以看到他们利用了这些性能差异:
隐式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
}
如果我们深入挖掘,请参阅Seq仅实现 + + ,它的列表性能比 ::: 用于追加操作。所以,要回答你的第二个问题,表现。如果scalaz为Seq实现了半群,那么很可能会导致性能不明确,因为您只能针对索引进行优化。 Iterable有同样的问题。
I'm fairly new to scalaz and I am trying to figure out why the following code works:
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.
Couple questions:
- Where is the implicit for ListSemigroup?
- Why isn't there one for Seq?
So, in Scalaz 7 there's an implicit List
to Monoid
function which gives you back a Monoid[List[A]]
. Monoid
extends SemiGroup
so we have List covered.
Seq
does not get this special treatment. There's no implicit conversion from Seq
to Monoid
or Semigroup
. There is an implicit IndexedSeq
to Monoid
, but this doesn't help us.
Why isn't there one for Seq? I don't know. Perhaps Seq violates some laws of monoids/semigroups so there is no conversion. 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
UPDATE
Looking at the scala doc it becomes more apparent why the scalaz folks went this way. List inherits LinearSeq which inherits Seq. IndexedSeq inherits 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. If you look at the scalaz signatures for append you can see that they take advantage of these performance differences:
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
}
If we dig deeper, we see that Seq only implements ++ which has worse performance on lists than ::: for append operations. 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. Iterable has the same issue.
这篇关于为什么列出一个半群但Seq不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!