scalabook
Equal
Формальное определение
Класс типов Equal
описывает тип, который можно сравнивать на наблюдаемое равенство.
Equal
должен следовать следующим законам:
- Рефлексивность:
x == x
для любогоx
- Неразличимость тождеств (антисимметрия): для любых
x
иy
, еслиx == y
, тоx
иy
неразличимы. - Личность неразличимых: для любых
x
иy
, еслиx
иy
неразличимы, тоx == y
Неразличимость формализует интуитивное представление о двух объектах, обладающих точно такими же свойствами.
Два значения x, y: A
неразличимы, если не существует такой функции f: A => Boolean
, что f(x)
- true
, а f(y)
- false
.
Эти законы влекут за собой симметрию и транзитивность, которые должно быть легче проверить, поскольку они не дают универсальной количественной оценки для всех возможных предикатов в языке:
- Симметричность:
x == y
тогда и только тогда, когдаy == x
- Транзитивность: если
x == y
иy == z
, тогдаx == z
Если есть преобразование f: G => F
, то из Equal[F]
можно получить Equal[G]
.
Определение в виде кода на Scala
trait Equal[F]: self =>
def equal(a1: F, a2: F): Boolean
def notEqual(a1: F, a2: F): Boolean = !equal(a1, a2)
def contramap[G](f: G => F): Equal[G] = (a1: G, a2: G) => self.equal(f(a1), f(a2))
Реализация
Реализация в Cats
import cats.*import cats.implicits.*
1 === 1 // true"Hello" =!= "World" // true123 === "123" // Не скомпилируется: Type Mismatch Error1.some =!= none[Int] // true
final case class Cat(name: String, age: Int, color: String)
given Eq[Cat] = Eq.instance[Cat] { (cat1, cat2) => (cat1.name === cat2.name ) && (cat1.age === cat2.age ) && (cat1.color === cat2.color) }
val cat1 = Cat("Garfield", 38, "orange and black")val cat2 = Cat("Heathcliff", 32, "orange and black")cat1 === cat2 // false
Реализация в ScalaZ
import scalaz.*import Scalaz.*List(1, 2, 3) === List(1, 2, 3) // trueList(1, 2, 3) =/= List(1, 2, 4) // true
Реализация в Spire
import spire.math.Rationalimport spire.syntax.all.*
Rational(2, 4) === Rational(3, 6) // trueRational(2, 6) =!= Rational(3, 6) // true
Ссылки: