英文:
How to add custom Semigroup instance for Int
问题
以下是已经翻译好的内容:
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) // 预期结果 16,实际结果 8
如何使自定义的 intSemigroup
正常工作?
英文:
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?
答案1
得分: 0
你导入了两个Semigroup[Int]
的实例:
- 通过
import cats.implicits._
- 通过
import SemigroupInstances._
编译器选择了来自cats.implicits._
的实例。
如果你移除那个导入,它就可以工作:https://scastie.scala-lang.org/avsmEturTRGkNEOCDxuXOA
如果你想了解更多编译器如何选择隐式实例的信息,请参考这篇帖子:https://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits/5598107#5598107
在你的具体情况下,原因似乎是来自cats
的实例的类型实际上是CommutativeGroup[Int]
:
implicit val catsKernelStdGroupForInt: CommutativeGroup[Int] = new IntGroup
因此,作为一个派生类(CommutativeGroup
扩展了Semigroup
),它被认为更具体,因此更受欢迎。
如果你将你的实例类型更改为CommutativeGroup[Int]
(尽管这在数学上是不正确的,但这不是关键),你会得到一个"模糊的给定实例"错误,因为编译器无法决定使用哪个实例:https://scastie.scala-lang.org/dzClDOYDSJ20P1SRpH72nA
英文:
You import two instances of Semigroup[Int]
:
- via
import cats.implicits._
- via
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: https://stackoverflow.com/questions/5598085/where-does-scala-look-for-implicits/5598107#5598107
In your specific case, the reason appears to be that the type of the instance from cats is actually CommutativeGroup[Int]
:
implicit val catsKernelStdGroupForInt: CommutativeGroup[Int] = new IntGroup
Hence, being a derived class (CommutativeGroup
extends Semigroup
), 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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论