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


#1

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?


#2

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…)


#3

This takes care of the issue! Thanks!