为什么列出一个半群但Seq不是? [英] Why is List a Semigroup but Seq is not?

查看:155
本文介绍了为什么列出一个半群但Seq不是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对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没有看到。



几个问题:


  1. ListSemigroup的隐式内容在哪里?

  2. 为什么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签名的追加,你可以看到他们利用了这些性能差异:

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

 隐式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实现了半群,那么很可能会导致性能不明确,因为您只能针对索引进行优化。 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:

  1. Where is the implicit for ListSemigroup?
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆