我正在阅读Scala with Cats,在本书的第一章中,他们描述了Eq
的用法。
其中一个练习是编写一个类型类的实例来验证两个 cats 的相等性。考虑一下:
模型
final case class Cat(name: String, age: Int, color: String)
类型类实例
import cats.Eq
import cats.syntax.eq._
import cats.instances.string._
import cats.instances.int._
import co.alejandrome.typeclass.model.Cat
object CatsEqInstances {
implicit val catsEq: Eq[Cat] = Eq.instance[Cat] {
(cata, catb) =>
cata.color === catb.color && cata.age === catb.age && cata.name === catb.name
}
}
单元测试
import co.alejandrome.typeclass.model.Cat
import org.scalatest.{FlatSpec, Matchers}
import cats.instances.option._
class EqTest extends FlatSpec with Matchers{
import CatsEqInstances._
"Eq" should "compare two cats" in {
val cat1 = Cat("Garfield", 38, "orange and black")
val cat2 = Cat("Heathcliff", 33, "orange and black")
catsEq.eqv(cat1, cat2) shouldBe false
val cat3 = Cat("Garfield", 38, "orange and black")
catsEq.eqv(cat1, cat3) shouldBe true
}
it should "compare two Optional cats" in {
val cat1 = Cat("Garfield", 38, "orange and black")
//val cat2 = Cat("Heathcliff", 33, "orange and black")
val optionCat1 = Option(cat1)
val optionCat2 = Option.empty[Cat]
optionCat1 === optionCat2
}
}
第一个测试工作正常,但第二个测试没有,因为===
运算符是最新的运算符,而不是Eq
运算符。
我探究了类型类是否有任何语法或暗示,但我找不到任何关于它的内容。我在this PR中看到了基于Bill Venner's solution的解决方案,但这仅适用于猫自己的单元测试。
我用EqSyntax
特征戳了戳但是我无法弄明白如何覆盖自己实施===
。
有没有办法做到这一点?或者这还没有实现?
由于
答案 0 :(得分:2)
我不确定我是否正确理解了您的问题,但看起来您可以根据您引用的PR重新使用Cats为自己的测试实现的内容。只需将测试类定义更改为
即可class EqTest extends FlatSpec with Matchers with cats.tests.StrictCatsEquality {
然后你可以编写诸如
之类的测试optionCat1 === optionCat2 shouldBe false
或
optionCat1 should !== (optionCat2)
并且他们将使用您的Eq[Cat]
定义(如果它被导入范围)。
基本上,我们的想法是ScalaTest ===
使用一些隐含的CanEqual
。因此,如果您提供(导入)自定义隐式实现 - 您可以更改===
在其中的工作方式。