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.