//Monoids for sets
implicit def setUnion[A] : Monoid[Set[A]] =
new Monoid[Set[A]] {
override def empty: Set[A] = Set.empty
override def combine(x: Set[A], y: Set[A]): Set[A] =
x ++ y
}
implicit val setUnion= new Monoid[Set[_]] {
override def empty: Set[_] = Set.empty //This compiles even though empty takes a type parameter
override def combine(x: Set[_], y: Set[_]): Set[_] =
x ++ y
}
The second implementation is never looked up by the compiler. Why?
The second implementation cannot have a type parameter. Hence I have replaced it with _. But is it the same as the first implementation which uses animplicit def as opposed to an implicit val.
Both implementations work and do the same, but the latter resolves differently. Take for example this method:
def concat[A : Monoid](a1: A, a2: A) = Monoid[A].combine(a1,a2)
If we pass it some sets, the resolution will fail with the latter monoid defined:
@ concat(Set(1,2), Set(3,4))
cmd13.sc:1: could not find implicit value for evidence parameter of type cats.Monoid[scala.collection.immutable.Set[Int]]
val res13 = concat(Set(1,2), Set(3,4))
As you can see from the error, the compiler is looking for a Monoid[Set[Int]], so the instance Monoid[Set[_]] is not specific enough. The compiler doesn’t know, that the less specific instance is allowed here. You can help it by adding an explicit type to the call: