Eq, Order и PartialOrder

Эти классы типов предоставляют типобезопасные функции эквивалентности и сравнения. Сравнение может быть полным (Order) или частичным (PartialOrder); хотя неопределенные элементы, такие как NaN или null, вызовут проблемы в реализациях по умолчанию (для чисел с плавающей запятой альтернативные реализации, которые учитывают NaN, могут быть импортированы из spire.optional.totalfloat.*).

Eq

Spire предоставляет класс типов Eq[A] для представления равенства типов. Это позволяет рассуждать о типах, для которых не существует полезного в вычислительном отношении понятия равенства, а также избегать ошибок программирования, вызванных универсальным равенством.

Eq[A] предоставляет два оператора:

Spire требует для eqv соблюдения законов отношения эквивалентности, а именно:

Свойство антисимметрии может показаться запутанным. Идея состоит в том, что если 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] обеспечивает все следующее:

Экземпляры Order[A] должны соблюдать следующие свойства:

Кроме того, общее упорядочивание по полям должно подчиняться следующим дополнительным законам:

(Это законы, обязательные для упорядоченных полей.)

В некоторых случаях пользователям может потребоваться использовать (или определять) общее упорядочивание, которое не соответствуют всем этим законам или может нарушать законы, требуемые другими структурами. Примером может служить лексикографический порядок комплексных чисел, который нарушает 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 оснащен отрицательными элементами -x, то:

Вышеуказанные законы подразумевают:

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 использует число 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] представлен первым в этом руководстве.


Ссылки: