
fj.Ord Maven / Gradle / Ivy
package fj;
import fj.data.Array;
import fj.data.Either;
import fj.data.List;
import fj.data.Natural;
import fj.data.NonEmptyList;
import fj.data.Option;
import fj.data.Set;
import fj.data.Stream;
import fj.data.Validation;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Comparator;
import static fj.Function.apply;
import static fj.Function.compose;
import static fj.Function.curry;
import static fj.Semigroup.semigroup;
import static fj.Semigroup.semigroupDef;
/**
* Tests for ordering between two objects.
*
* @version %build.number%
*/
public final class Ord {
/**
* Primitives functions of Ord: minimal definition and overridable methods.
*/
public interface Definition extends Equal.Definition, Semigroup.Definition {
F compare(A a);
default Ordering compare(A a1, A a2) {
return compare(a1).f(a2);
}
// equal:
@Override
default boolean equal(A a1, A a2) {
return compare(a1, a2) == Ordering.EQ;
}
@Override
default F equal(A a) {
return compose(o -> o == Ordering.EQ, compare(a));
}
// max semigroup:
@Override
default A append(A a1, A a2) {
return compare(a1, a2) == Ordering.GT ? a1 : a2;
}
@Override
default A multiply1p(int n, A a) {
return a;
}
@Override
default F prepend(A a1) {
return apply((a2, o) -> o == Ordering.GT ? a1 : a2, compare(a1));
}
@Override
default Definition dual() {
return new Definition() {
@Override
public F compare(A a) {
return compose(Ordering::reverse, Definition.this.compare(a));
}
@Override
public Ordering compare(A a1, A a2) {
return Definition.this.compare(a2, a1);
}
@Override
public Definition dual() {
return Definition.this;
}
};
}
/**
* Refine this ord definition: compares using self and if objects are equal compares using given Ord
.
* @see #ord()
*
* @param bOrd Ord for subsequent comparison
* @return A new ord definition.
*/
default Definition then(final F f, final Ord bOrd) {
Definition bOrdDef = bOrd.def;
return new Definition() {
@Override
public F compare(A a1) {
F fa = Definition.this.compare(a1);
F fb = bOrdDef.compare(f.f(a1));
return a2 -> {
Ordering aOrdering = fa.f(a2);
return aOrdering != Ordering.EQ ? aOrdering : fb.f(f.f(a2));
};
}
@Override
public Ordering compare(A a1, A a2) {
Ordering aOrdering = Definition.this.compare(a1, a2);
return aOrdering != Ordering.EQ ? aOrdering : bOrdDef.compare(f.f(a1), f.f(a2));
}
};
}
/**
* Build an ord instance from this definition.
* to be called after some successive {@link #then(F, Ord)} calls.
*/
default Ord ord() {
return ordDef(this);
}
}
/**
* Primitives functions of Ord: alternative minimal definition and overridable methods.
*/
public interface AltDefinition extends Definition {
Ordering compare(A a1, A a2);
default F compare(A a1) {
return a2 -> compare(a1, a2);
}
@Override
default F prepend(A a1) {
return a2 -> append(a1, a2);
}
}
private final Definition def;
private Ord(final Definition def) {
this.def = def;
this.max = a1 -> apply((a2, o) -> o == Ordering.GT ? a1 : a2, def.compare(a1));
this.min = a1 -> apply((a2, o) -> o == Ordering.LT ? a1 : a2, def.compare(a1));
}
/**
* First-class ordering.
*
* @return A function that returns an ordering for its arguments.
*/
public F> compare() {
return def::compare;
}
/**
* Returns an ordering for the given arguments.
*
* @param a1 An instance to compare for ordering to another.
* @param a2 An instance to compare for ordering to another.
* @return An ordering for the given arguments.
*/
public Ordering compare(final A a1, final A a2) {
return def.compare(a1, a2);
}
/**
* Returns true
if the given arguments are equal, false
otherwise.
*
* @param a1 An instance to compare for equality to another.
* @param a2 An instance to compare for equality to another.
* @return true
if the given arguments are equal, false
otherwise.
*/
public boolean eq(final A a1, final A a2) {
return def.compare(a1, a2) == Ordering.EQ;
}
/**
* Returns an Equal
for this order.
*
* @return An Equal
for this order.
*/
public Equal equal() {
return Equal.equalDef(def);
}
/**
* Maps the given function across this ord as a contra-variant functor.
*
* @param f The function to map.
* @return A new ord.
*/
public Ord contramap(final F f) {
return ordDef(contramapDef(f, def));
}
/**
* Returns true
if the first given argument is less than the second given argument,
* false
otherwise.
*
* @param a1 An instance to compare for ordering to another.
* @param a2 An instance to compare for ordering to another.
* @return true
if the first given argument is less than the second given argument,
* false
otherwise.
*/
public boolean isLessThan(final A a1, final A a2) {
return def.compare(a1, a2) == Ordering.LT;
}
/**
* Returns true
if the first given argument is less than or equal to the second given argument,
* false
otherwise.
*
* @param a1 An instance to compare for ordering to another.
* @param a2 An instance to compare for ordering to another.
* @return true
if the first given argument is less than or equal to the second given argument,
* false
otherwise.
*/
public boolean isLessThanOrEqualTo(final A a1, final A a2) {
return def.compare(a1, a2) != Ordering.GT;
}
/**
* Returns true
if the first given argument is greater than the second given
* argument, false
otherwise.
*
* @param a1 An instance to compare for ordering to another.
* @param a2 An instance to compare for ordering to another.
* @return true
if the first given argument is greater than the second given
* argument, false
otherwise.
*/
public boolean isGreaterThan(final A a1, final A a2) {
return def.compare(a1, a2) == Ordering.GT;
}
/**
* Returns a function that returns true if its argument is less than the argument to this method.
*
* @param a A value to compare against.
* @return A function that returns true if its argument is less than the argument to this method.
*/
public F isLessThan(final A a) {
return compose(o -> o == Ordering.GT, def.compare(a));
}
/**
* Returns a function that returns true if its argument is greater than than the argument to this method.
*
* @param a A value to compare against.
* @return A function that returns true if its argument is greater than the argument to this method.
*/
public F isGreaterThan(final A a) {
return compose(o -> o == Ordering.LT, def.compare(a));
}
/**
* Returns the greater of its two arguments.
*
* @param a1 A value to compare with another.
* @param a2 A value to compare with another.
* @return The greater of the two values.
*/
public A max(final A a1, final A a2) {
return def.append(a1, a2);
}
/**
* Returns the lesser of its two arguments.
*
* @param a1 A value to compare with another.
* @param a2 A value to compare with another.
* @return The lesser of the two values.
*/
public A min(final A a1, final A a2) {
return isLessThan(a1, a2) ? a1 : a2;
}
/**
* A function that returns the greater of its two arguments.
*
*/
public final F> max;
/**
* A function that returns the lesser of its two arguments.
*/
public final F> min;
public final Semigroup minSemigroup() {
return semigroupDef(def.dual());
}
public final Monoid minMonoid(A zero) {
return Monoid.monoidDef(def.dual(), zero);
}
public final Semigroup maxSemigroup() {
return semigroupDef(def);
}
public final Monoid maxMonoid(A zero) {
return Monoid.monoidDef(def, zero);
}
public final Ord reverse() {
return ordDef(def.dual());
}
/**
* Begin definition of an ord instance.
* @see Definition#then(F, Equal)
*/
public static Definition on(final F f, final Ord ord) {
return contramapDef(f, ord.def);
}
/**
* Static version of {@link #contramap(F)}
*/
public static Ord contramap(final F f, final Ord ord) {
return ordDef(contramapDef(f, ord.def));
}
private static Definition contramapDef(F f, Definition def) {
return new Definition() {
@Override
public F compare(B b) {
return compose(def.compare(f.f(b)), f);
}
@Override
public Ordering compare(B b1, B b2) {
return def.compare(f.f(b1), f.f(b2));
}
};
}
/**
* Returns an order instance that uses the given equality test and ordering function.
*
* Java 8+ users: use {@link #ordDef(Definition)} instead.
*
* @param f The order function.
* @return An order instance.
*/
public static Ord ord(final F> f) {
return new Ord<>(f::f);
}
/**
* Returns an order instance that uses the given equality test and ordering function.
*
* Java 8+ users: use {@link #ordDef(AltDefinition)} instead.
*
* @param f The order function.
* @return An order instance.
*/
public static Ord ord(final F2 f) {
return ordDef(f::f);
}
/**
* Returns an order instance that uses the given minimal equality test and ordering definition.
*
* @param def The order definition.
* @return An order instance.
*/
public static Ord ordDef(final Definition def) {
return new Ord<>(def);
}
/**
* Returns an order instance that uses the given minimal equality test and ordering definition.
*
* @param def The order definition.
* @return An order instance.
*/
public static Ord ordDef(final AltDefinition def) {
return new Ord<>(def);
}
/**
* An order instance for the boolean
type.
*/
public static final Ord booleanOrd = comparableOrd();
/**
* An order instance for the byte
type.
*/
public static final Ord byteOrd = comparableOrd();
/**
* An order instance for the char
type.
*/
public static final Ord charOrd = comparableOrd();
/**
* An order instance for the double
type.
*/
public static final Ord doubleOrd = comparableOrd();
/**
* An order instance for the float
type.
*/
public static final Ord floatOrd = comparableOrd();
/**
* An order instance for the int
type.
*/
public static final Ord intOrd = comparableOrd();
/**
* An order instance for the BigInteger
type.
*/
public static final Ord bigintOrd = comparableOrd();
/**
* An order instance for the BigDecimal
type.
*/
public static final Ord bigdecimalOrd = comparableOrd();
/**
* An order instance for the long
type.
*/
public static final Ord longOrd = comparableOrd();
/**
* An order instance for the short
type.
*/
public static final Ord shortOrd = comparableOrd();
/**
* An order instance for the {@link Ordering} type.
*/
public static final Ord orderingOrd = ordDef((o1, o2) -> o1 == o2 ?
Ordering.EQ :
o1 == Ordering.LT ?
Ordering.LT :
o2 == Ordering.LT ?
Ordering.GT :
o1 == Ordering.EQ ?
Ordering.LT :
Ordering.GT);
/**
* An order instance for the {@link String} type.
*/
public static final Ord stringOrd = comparableOrd();
/**
* An order instance for the {@link StringBuffer} type.
*/
public static final Ord stringBufferOrd = stringOrd.contramap(StringBuffer::toString);
/**
* An order instance for the {@link StringBuffer} type.
*/
public static final Ord stringBuilderOrd = stringOrd.contramap(StringBuilder::toString);
/**
* An order instance for the {@link Option} type.
*
* @param oa Order across the element of the option.
* @return An order instance for the {@link Option} type.
*/
public static Ord
© 2015 - 2025 Weber Informatics LLC | Privacy Policy