Eq 

LYAHFGG:

Eq is used for types that support equality testing. The functions its members implement are == and /=.

Cats’ equivalent for the Eq typeclass is also called Eq. Eq was moved from non/algebra into cats-kernel subproject, and became part of Cats:

scala> import cats._, cats.data._, cats.implicits._
import cats._
import cats.data._
import cats.implicits._

scala> 1 === 1
res4: Boolean = true

scala> 1 === "foo"
<console>:40: error: type mismatch;
 found   : String("foo")
 required: Int
       1 === "foo"
             ^

scala> 1 == "foo"
<console>:40: warning: comparing values of types Int and String using `==' will always yield false
       1 == "foo"
         ^
res6: Boolean = false

scala> (Some(1): Option[Int]) =!= (Some(2): Option[Int])
res7: Boolean = true

Instead of the standard ==, Eq enables === and =!= syntax by declaring eqv method. The main difference is that === would fail compilation if you tried to compare Int and String.

In algebra, neqv is implemented based on eqv.

/**
 * A type class used to determine equality between 2 instances of the same
 * type. Any 2 instances `x` and `y` are equal if `eqv(x, y)` is `true`.
 * Moreover, `eqv` should form an equivalence relation.
 */
trait Eq[@sp A] extends Any with Serializable { self =>

  /**
   * Returns `true` if `x` and `y` are equivalent, `false` otherwise.
   */
  def eqv(x: A, y: A): Boolean

  /**
   * Returns `false` if `x` and `y` are equivalent, `true` otherwise.
   */
  def neqv(x: A, y: A): Boolean = !eqv(x, y)

  ....
}

This is an example of polymorphism. Whatever equality means for the type A, neqv is the opposite of it. It does not matter if it’s String, Int, or whatever. Another way of looking at it is that given Eq[A], === is universally the opposite of =!=.

I’m a bit concerned that Eq seems to be using the terms “equal” and “equivalent” interchangably. Equivalence relationship could include “having the same birthday” whereas equality also requires substitution property.