24

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

セミグループのマップは暗黙的に表示されますが、リストまたはシーケンスのマップは表示されません。

カップルの質問:

  1. ListSemigroupの暗黙の場所はどこですか?
  2. Seq用のものがないのはなぜですか?
4

1 に答える 1

29

したがって、Scalaz 7には、を返す暗黙ListMonoid関数がありますMonoid[List[A]]Monoid拡張SemiGroupするので、リストがカバーされます。

Seqこの特別な扱いは受けません。SeqからMonoidまたはへの暗黙の変換はありませんSemigroup。には暗黙IndexedSeqMonoidがありますが、これは役に立ちません。

Seq用のものがないのはなぜですか?知らない。おそらく、Seqはモノイド/半群のいくつかの法則に違反しているため、変換は行われません。Scalaz 6のSeqに問題があったようで、いくつかの機能が削除されました: https ://groups.google.com/forum/?fromgroups=#!searchin/scalaz/Seq/scalaz/Deaec1H11W4/gYFSquXjTzYJ

アップデート

スカラのドキュメントを見ると、スカラの人々がこのように行った理由がより明らかになります。リストはSeqを継承するLinearSeqを継承します。IndexedSeqはSeqを継承します。それらがSeqの半群を提供する場合、IndexedSeqまたはLinearSeqの他の半群をオーバーライドし、2つの間のパフォーマンス上の利点を失う可能性があります。appendのscalazシグネチャを見ると、これらのパフォーマンスの違いを利用していることがわかります。

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は++のみを実装していることがわかります。これは、追加操作の場合よりもリストでのパフォーマンスが劣ります。それで、あなたの2番目の質問に答えるために、パフォーマンス。scalazがSeqの半群を実装した場合、インデックス付きに最適化することしかできないため、パフォーマンスがあいまいになる可能性があります。Iterableにも同じ問題があります。

于 2013-03-25T21:07:42.093 に答える