## 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:

``````import cats._, cats.syntax.all._

1 === 1
// res0: Boolean = true
``````
``````1 === "foo"
// error: type mismatch;
//  found   : String("foo")
//  required: Int
// 1 === "foo"
//       ^^^^^
``````
``````(Some(1): Option[Int]) =!= (Some(2): Option[Int])
// res2: 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.