我想為某些型別定義相等性,這些型別可以是使用貓/小貓的其他物件或集合的一部分。我不想為每個其他類定義相等性。例如:
import cats.Eq
case class Foo(a: Int, bar: Bar)
case class Bar(b: Int)
object BarEq {
implicit val barEq: Eq[Bar] = Eq.instance[Bar] {
(b1, b2) => b1.b 1 == b2.b
}
}
然后測驗定義為
import cats.derived.auto.eq._
class BarEqTest extends FlatSpec with cats.tests.StrictCatsEquality {
import BarEq._
"bareq" should {
"work" in {
Foo(1, Bar(1)) should ===(Foo(1, Bar(2)))
Bar(1) should ===(Bar(2))
Some(Foo(1, Bar(1))) should ===(Some(Foo(1, Bar(2))))
}
}
}
這作業正常,但如果我嘗試添加以下測驗用例
Seq(Foo(1, Bar(1))) should ===(Seq(Foo(1, Bar(2))))
我得到
[Error] types Seq[Foo] and Seq[Foo] do not adhere to the type constraint selected for the === and !== operators; the missing implicit parameter is of type org.scalactic.CanEqual[Seq[Foo],Seq[Foo]]
one error found
為什么自動派生的 eq 可以使用Option但不能使用Seq,我該如何讓它作業?我試圖添加,import cats.instances.seq._但這也不起作用。
uj5u.com熱心網友回復:
Cats 定義了一個Eqfor實體,而scala.collection.immutable.Seq不是泛型scala.collection.Seq(或者此外scala.collection.mutable.Seq)
import scala.collection.immutable.{BitSet, Queue, Seq, SortedMap, SortedSet}
private[kernel] trait EqInstances0 {
implicit def catsKernelEqForSeq[A: Eq]: Eq[Seq[A]] = cats.kernel.instances.seq.catsKernelStdEqForSeq[A]
}
https://github.com/typelevel/cats/blob/main/kernel/src/main/scala/cats/kernel/Eq.scala#L283-L285
從 Scala 2.13.0 開始scala.Seq是scala.collection.immutable.Seq. 但在 Scala 2.12.x 中scala.Seq是scala.collection.Seq.
https://github.com/scala/scala/releases/tag/v2.13.0
所以在 Scala 2.12 中匯入正確的集合型別
import scala.collection.immutable.Seq
Seq(Foo(1, Bar(1))) === Seq(Foo(1, Bar(2))) // true
或Eq為必要的集合定義您自己的實體
import cats.kernel.instances.StaticMethods
implicit def genericSeqEq[A: Eq]: Eq[collection.Seq[A]] = new Eq[collection.Seq[A]] {
override def eqv(xs: collection.Seq[A], ys: collection.Seq[A]): Boolean =
if (xs eq ys) true
else StaticMethods.iteratorEq(xs.iterator, ys.iterator)
}
Seq(Foo(1, Bar(1))) === Seq(Foo(1, Bar(2))) // true
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/327836.html
