How to resolve implicit collision with cats.Eq === and scalatest?

Hi,

I am following ‘Scala with Cats’ book and I have following code to test cats.Eq.

import com.example.cats.eq.CatsEq._
import org.scalatest.FunSpec

class CatsEqSpec extends FunSpec with Cats {

  describe("Cats Eq") {
    it("should correctly tell when two cats are equal or not equal") {
      import cats.syntax.eq._
      garfieldCat === heathcliffCat should be(false)
      garfieldCat =!= heathcliffCat should be(true)
    }
  }

}


package com.example.cats.eq

import cats.Eq
import com.example.Cat
import cats.instances.int._
import cats.instances.string._
import cats.syntax.eq._

object CatsEq {

  implicit val catEq: Eq[Cat] = Eq.instance[Cat] {
    (firstCat, secondCat) =>
      (firstCat.name === secondCat.name) &&
      (firstCat.color === secondCat.color) &&
      (firstCat.age === secondCat.age)
  }

}

I get following error with it:

[error] /scala-with-cats-lab/src/test/scala/CatsEqSpec.scala:9: type mismatch;
[error]  found   : CatsEqSpec.this.garfieldCat.type (with underlying type com.example.Cat)
[error]  required: ?{def ===(x$1: ? >: com.example.Cat): ?}
[error] Note that implicit conversions are not applicable because they are ambiguous:
[error]  both method convertToEqualizer in trait TripleEquals of type [T](left: T)CatsEqSpec.this.Equalizer[T]
[error]  and method catsSyntaxEq in trait EqSyntax of type [A](a: A)(implicit evidence$1: cats.Eq[A])cats.syntax.EqOps[A]
[error]  are possible conversion functions from CatsEqSpec.this.garfieldCat.type to ?{def ===(x$1: ? >: com.example.Cat): ?}
[error]       garfieldCat === heathcliffCat should be(false)
[error]       ^

What is the simplest way to fix this? Is there a direct way to say that I do not want (or shadow) TripleEquals.convertToEqualizer in the current scope?

It suffices to shadow the ScalaTest one locally, like

it("should correctly tell when two cats are equal or not equal") {
  val convertToEqualizer = ()  // shadow ScalaTest
  import cats.syntax.eq._
  garfieldCat === heathcliffCat should be(false)
  garfieldCat =!= heathcliffCat should be(true)
}

(the downside is the compiler warns you that the value convertToEqualizer is never used…)

This takes care of the issue! Thanks!

If the purpose of the tests is to make sure that catEq works correctly, then checking =!= could be sufficient. =!= is not defined in scalactic, so catEq actually gets called.
We can trust that outside of scalactic context === is an opposite to =!= and this has been already tested within Cats.

You might use eqv instead of ===