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

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

问题描述

我对 scalaz 还很陌生,我想弄清楚为什么下面的代码有效:

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

但这并没有...

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

我看到了半群隐含的 Map,但我没有看到 List 或 Seq 的映射.

I see the Map implicit for Semigroup, but I don't see the one for List or Seq.

几个问题:

  1. ListSemigroup 的隐式在哪里?
  2. 为什么 Seq 没有​​?

推荐答案

所以,在 Scalaz 7 中有一个 隐式 ListMonoid 函数,它给你一个Monoid[List[A]].Monoid 扩展了 SemiGroup 所以我们已经覆盖了 List.

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 没有得到这种特殊处理.没有从 SeqMonoidSemigroup 的隐式转换.有一个 IndexedSeq隐含到Monoid,但这对我们没有帮助.

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.

为什么 Seq 没有​​?我不知道.也许 Seq 违反了幺半群/半群的一些定律,所以没有转换.Scalaz 6 中的 Seq 似乎存在问题,因此他们删除了一些功能:https://groups.google.com/forum/?fromgroups=#!searchin/scalaz/Seq/scalaz/Deaec1H11W4/gYFSquXjTzYJ

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

更新

查看 scala 文档,scalaz 人为什么要这样做变得更加明显.List 继承了继承了 Seq 的 LinearSeq.IndexedSeq 继承了 Seq.如果他们为 Seq 提供一个半群,它可能会覆盖 IndexedSeq 或 LinearSeq 上的任何其他半群,并在两者之间失去性能优势.如果您查看 append 的 scalaz 签名,您会发现它们利用了这些性能差异:

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
  }

如果我们深入挖掘,我们会看到 Seq 只实现了 ++ 在列表上的性能比 ::: 用于追加操作.所以,回答你的第二个问题,性能.如果 scalaz 为 Seq 实现了半群,它很可能会导致性能不明确,因为您只能针对索引进行优化.Iterable 也有同样的问题.

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.

这篇关于为什么 List 是一个半群而 Seq 不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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