fj.Ord Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of functionaljava Show documentation
Show all versions of functionaljava Show documentation
Functional Java is an open source library that supports closures for the Java programming language
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;
}
};
}
}
/**
* 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) {
Definition selfDef = def;
return ordDef(new Definition() {
@Override
public F compare(B b) {
return compose(selfDef.compare(f.f(b)), f);
}
@Override
public Ordering compare(B b1, B b2) {
return selfDef.compare(f.f(b1), f.f(b2));
}
});
}
/**
* 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());
}
/**
* 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