Eq, Order и PartialOrder
Эти классы типов предоставляют типобезопасные функции эквивалентности и сравнения.
Сравнение может быть полным (Order
) или частичным (PartialOrder
);
хотя неопределенные элементы, такие как NaN
или null
, вызовут проблемы в реализациях по умолчанию
(для чисел с плавающей запятой альтернативные реализации, которые учитывают NaN
,
могут быть импортированы из spire.optional.totalfloat.*
).
Eq
Spire предоставляет класс типов Eq[A]
для представления равенства типов.
Это позволяет рассуждать о типах, для которых не существует полезного в вычислительном отношении понятия равенства,
а также избегать ошибок программирования, вызванных универсальным равенством.
Eq[A]
предоставляет два оператора:
eqv
(===
): эквивалентность - проверка на равенство.neqv
(=!=
): различие - проверка на отсутствие равенства (по умолчанию!(a === b)
).
Spire требует для eqv
соблюдения законов отношения эквивалентности, а именно:
a === a
(рефлексивность)- если
a === b
, тогдаb === a
(симметрия) - если
a === b
, тоa
естьb
(антисимметрия) - если
a === b
иb === c
, тогдаa === c
(транзитивность)
Свойство антисимметрии может показаться запутанным.
Идея состоит в том, что если a === b
, тогда a
и b
должны быть взаимозаменяемыми,
так что для любого выражения f(x)
, f(a) === f(b)
.
import spire.math.Rational
import spire.syntax.all.*
Rational(2, 4) === Rational(3, 6) // true
Rational(2, 6) =!= Rational(3, 6) // true
Order
Общее сравнение в Spire поддерживается классом типов Order[A]
.
В отличие от других классов типов упорядочивания (например, scala.math.Ordering
),
этот специализируется на том, чтобы избежать упаковки Order[A]
.
Расширение Eq[A]
можно реализовать с помощью одного метода compare
,
хотя Order[A]
обеспечивает все следующее:
eqv
(a === b
)neqv
(a =!= b
)compare
(a compare b
): меньше (-1
), равно (0
) или больше (1
)gt
(a > b
): большеgteqv
(a >= b
): больше или равноlt
(a < b
): меньшеlteqv
(a <= b
): меньше или равноmin
(a min b
): наименьший элементmax
(a max b
): наибольший элемент
Экземпляры Order[A]
должны соблюдать следующие свойства:
- если
a <= b
иb <= a
, тогдаa === b
(антисимметрия) - если
a <= b
иb <= c
, тогдаa <= c
(транзитивность) - либо
a <= b
илиb <= a
(полнота)
Кроме того, общее упорядочивание по полям должно подчиняться следующим дополнительным законам:
- если
a <= b
, тогда(a + c) <= (b + c)
(O1) - если
zero <= a
иzero <= b
, тогдаzero <= (a * b)
(O2)
(Это законы, обязательные для упорядоченных полей.)
В некоторых случаях пользователям может потребоваться использовать (или определять) общее упорядочивание, которое не соответствуют всем этим законам или может нарушать законы, требуемые другими структурами. Примером может служить лексикографический порядок комплексных чисел, который нарушает O2. В этих случаях пользователям необходимо будет осознавать риски и ограничивать их использование ситуациями, когда конкретный закон не требуется.
import spire.algebra.Order
import spire.math.Rational
Order.comparison(Rational(1, 2), Rational(1, 3)) // GreaterThan
Order.gt(Rational(1, 2), Rational(1, 3)) // true
Order.gteqv(Rational(1, 2), Rational(1, 3)) // true
Order.lt(Rational(1, 2), Rational(1, 3)) // false
Order.lteqv(Rational(1, 2), Rational(1, 3)) // false
Order.min(Rational(1, 2), Rational(1, 3)) // 1/3
Order.max(Rational(1, 2), Rational(1, 3)) // 1/2
Signed
Общее упорядочивание, инвариантное к сдвигу, фиксируется классом типов Signed[A]
-
типы, имеющие знак (отрицательный, ноль, положительный).
В общем случае тип A
оснащен коммутативной аддитивной операцией +
и нулевым элементом 0
(см. определение коммутативных колец ниже).
Действуют следующие законы:
- если
a <= b
, тогдаa + c <= b + c
(линейный порядок), signum(x) = -1
еслиx < 0
,signum(x) = 1
еслиx > 0
, иначе -signum(x) = 0
.
Если тип A
оснащен отрицательными элементами -x
, то:
abs(x) = -x
еслиx < 0
, иначе -x
,
Вышеуказанные законы подразумевают:
abs(a + b) <= abs(a) + abs(b)
import spire.algebra.Signed.*
import spire.std.int.*
sign(10) // Positive
sign(0) // Zero
sign(-10) // Negative
signum(10) // 1
signum(0) // 0
signum(-10) // -1
abs(10) // 10
abs(0) // 0
abs(-10) // 10
isSignPositive(10) // true
isSignZero(0) // true
isSignNegative(-10) // true
isSignNonPositive(10) // false
isSignNonZero(0) // false
isSignNonNegative(-10) // false
PartialOrder
Частичное упорядочивание в Spire поддерживается классом типов PartialOrder[A]
.
Его реализация отличается от scala.math.PartialOrdering
двумя особенностями:
PartialOrder
специализирована для предотвращения упаковки, а метод partialCompare
возвращает Double
и избегает выделения экземпляра Option[Int]
.
PartialOrder[A]
расширяет Eq[A]
и может быть реализован с помощью одного метода partialCompare
, описанного ниже.
PartialOrder
обеспечивает:
partialCompare
(a partialCompare b
): меньше (-1.0
), равно (0.0
), больше (1.0
) или невозможность сравнения (NaN
)tryCompare
(a tryCompare b
): меньше (Some(-1)
), равно (Some(0)
), больше (Some(1)
) или невозможность сравнения (None
)pmin
(a pmin b
): нахождение наименьшего элемента, если элементы сравнимы; возвращаетсяOption
pmax
(a pmax b
): нахождение наибольшего элемента, если элементы сравнимы; возвращаетсяOption
gt
(a > b
),gteqv
(a >= b
),lt
(a < b
) иlteqv
(a <= b
): возвращаетсяfalse
если элементы не сравнимы или результат сравненияeqv
(a === b
)neqv
(a =!= b
)
Частичное упорядочивание определяется бинарным отношением <=
, которое удовлетворяет отношениям:
a <= a
(рефлексивность)- если
a <= b
иb <= a
, тоa === b
(антисимметрия) - если
a <= b
иb <= c
, тоa <= c
(транзитивность)
Чтобы вычислить оба значения <=
и >=
одновременно,
метод partialCompare
использует число Double
для кодирования результата обоих сравнений.
Таблица истинности определяется следующим образом:
a <= b |
a >= b |
partialCompare(a, b) |
соответствует |
---|---|---|---|
true |
true |
0 |
a === b |
false |
false |
NaN |
a несравнима с b |
true |
false |
-1 |
a < b |
false |
true |
1 |
a > b |
Метод tryCompare
возвращает вместо -1.0
, 0.0
, 1.0
, NaN
соответственно Some(-1)
, Some(0)
, Some(1)
и None
,
что позволяет использовать метод getOrElse
и методы более высокого порядка по стоимости выделения Option[Int]
.
Экземпляры PartialOrder[A]
необходимы для соблюдения вышеуказанных свойств.
Обратите внимание, что Order[A]
расширяет PartialOrder[A]
,
но в педагогических целях, Order[A]
представлен первым в этом руководстве.
Ссылки: