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
toMonoid
function which gives you back aMonoid[List[A]]
.Monoid
extendsSemiGroup
so we have List covered.Seq
does not get this special treatment. There's no implicit conversion fromSeq
toMonoid
orSemigroup
. There is an implicitIndexedSeq
toMonoid
, 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
https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/std/IndexedSeq.scala
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.