import cats._
import cats.implicits._
object SemigroupInstances {
implicit val intSemigroup: Semigroup[Int] = new Semigroup[Int] {
override def combine(a: Int, b: Int) = a * b
}
}
import SemigroupInstances._
object Semigroup {
def apply[T](implicit instance: Semigroup[T]): Semigroup[T] = instance
}
val intSemigroup = Semigroup[Int]
intSemigroup.combine(4, 4) // expected 16, actual 8
So, how to make custom intSemigroup working?
You import two instances of
Semigroup[Int]:import cats.implicits._import SemigroupInstances._The compiler chooses the one from
cats.implicits._over your custom instance.If you remove that import, it works: https://scastie.scala-lang.org/avsmEturTRGkNEOCDxuXOA
If you want to know more about how the compiler chooses which implicit instance to use, see this post: Where does Scala look for implicits?
In your specific case, the reason appears to be that the type of the instance from cats is actually
CommutativeGroup[Int]:Hence, being a derived class (
CommutativeGroupextendsSemigroup), it is considered more specific and hence preferred.If you change the type of your instance to
CommutativeGroup[Int](which is not possible without being mathematically incorrect, but that's not the point here), you get an "Ambiguous given instances" error because the compiler cannot decide which instance to use: https://scastie.scala-lang.org/dzClDOYDSJ20P1SRpH72nA