scalabook

Форк
0
177 строк · 10.4 Кб

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


Ссылки:

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.