PartialOrderOrEq
If you are using the Cats library, you can define a PartialOrder
type class for any data type.
- Scala 3
- Scala 2.13
// Simplified definition.
// See https://typelevel.org/cats/api/cats/kernel/PartialOrder.html for further details
trait PartialOrder[A]:
def partialCompare(x: A, y: A): Double
// Simplified definition.
// See https://typelevel.org/cats/api/cats/kernel/PartialOrder.html for further details
trait PartialOrder[A] {
def partialCompare(x: A, y: A): Double
}
The PartialOrder
type provides a method for comparing two objects of the given type, returning a double value of:
- 0.0 if the two objects are equivalent
- -1.0 if
x < y
- 1.0 if
x < y
NaN
ifx
andy
cannot be compared.
Cats is also kind enough to provide implicit <
, <=
, ===
, >=
and >
operators if the given type does not provide them already.
That's all nice, but not every type comes with a given PartialOrder
for us to use.
But logically, it must be possible to define a PartialOrder
for every type; even if it is very partial!
The couldbe-cats
package provides a ready implementation of PartialOrderOrEq
:
- Scala 3
- Scala 2.13
trait PartialOrderOrEq[A: CouldHave[PartialOrder]: EqOrEquals]:
def p(x: A, y: A): Double =
CouldHave[PartialOrder, A]
.act(_.partialCompare(x, y))
(if EqOrEquals.e(x, y) then 0.0 else Double.NaN)
trait PartialOrderOrEq[A: EqOrEquals](A: CouldHave[PartialOrder, A]) {
def p(x: A, y: A): Double =
CouldHave[PartialOrder, A]
.act(_.partialCompare(x, y))
(if (EqOrEquals.e(x, y)) 0.0 else Double.NaN)
}
This is a "best attempt" at a partial order for any given type.
In the following function
- Scala 3
- Scala 2.13
def yourFunction[A: PartialOrderOrEq](x: A, y: A):
// ...
PartialOrderOrEq.p(x, y)
// ...
def yourFunction[A: PartialOrderOrEq](x: A, y: A) {
// ...
PartialOrderOrEq.p(x, y)
// ...
}
the following rules will be applied:
- if a given
PartialOrder
(or a completeOrder
, which extends the trait) exists, then that instance will be used to perform the comparison - otherwise, if a given
Eq
(Cats Equality) instance exists, then the function will return 0.0 ifx === y
;NaN
otherwise - finally, if we still have no comparison, the two values will be compared using the JVM
.equals()
method; returning 0.0 ifx.equals(y)
orNaN
otherwise.