添加Int的自定义Semigroup实例的方法

huangapple go评论65阅读模式
英文:

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]的实例:

  1. 通过import cats.implicits._
  2. 通过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]:

  1. via import cats.implicits._
  2. 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

huangapple
  • 本文由 发表于 2023年5月14日 21:40:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76247767.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定