
fj.Equal Maven / Gradle / Ivy
package fj;
import fj.data.*;
import fj.data.hamt.BitSet;
import fj.data.hlist.HList;
import fj.data.optic.Traversal;
import fj.data.vector.V2;
import fj.data.vector.V3;
import fj.data.vector.V4;
import fj.data.vector.V5;
import fj.data.vector.V6;
import fj.data.vector.V7;
import fj.data.vector.V8;
import fj.parser.Result;
import java.math.BigDecimal;
import java.math.BigInteger;
import static fj.Function.compose;
import static fj.Function.constant;
import static fj.Function.curry;
/**
* Tests for equality between two objects.
*
* @version %build.number%
*/
public final class Equal {
/**
* Primitives functions of Equal: minimal definition and overridable methods.
*/
public interface Definition {
F equal(A a);
default boolean equal(A a1, A a2) {
return equal(a1).f(a2);
}
/**
* Refine this equal definition, to tests equality of self and the mapped object in "and" manner.
* @see #equal()
*
* @param f The function to map the original object
* @param eq Equality for the mapped object
* @return A new equal definition
*/
default Definition then(final F f, final Equal eq) {
Definition bEqDef = eq.def;
return new Definition() {
@Override
public F equal(A a1) {
F fa = Definition.this.equal(a1);
F fb = bEqDef.equal(f.f(a1));
return a2 -> fa.f(a2) && fb.f(f.f(a2));
}
@Override
public boolean equal(A a1, A a2) {
return Definition.this.equal(a1, a2) && bEqDef.equal(f.f(a1), f.f(a2));
}
};
}
/**
* Build an equal instance from this definition.
* to be called after some successive {@link #then(F, Equal)} calls.
*/
default Equal equal() {
return equalDef(this);
}
}
/**
* Primitives functions of Equal: alternative minimal definition and overridable methods.
*/
public interface AltDefinition extends Definition {
@Override
boolean equal(A a1, A a2);
@Override
default F equal(A a) {
return a2 -> equal(a, a2);
}
}
private final Definition def;
private Equal(final Definition def) {
this.def = def;
}
/**
* Returns true
if the two given arguments are equal, false
otherwise.
*
* @param a1 An object to test for equality against another.
* @param a2 An object to test for equality against another.
* @return true
if the two given arguments are equal, false
otherwise.
*/
public boolean eq(final A a1, final A a2) {
return def.equal(a1, a2);
}
/**
* Returns true
if the two given arguments are not equal, false
otherwise.
*
* @param a1 An object to test for inequality against another.
* @param a2 An object to test for inequality against another.
* @return true
if the two given arguments are not equal, false
otherwise.
*/
public boolean notEq(final A a1, final A a2) {
return !def.equal(a1, a2);
}
/**
* First-class equality check.
*
* @return A function that returns true
if the two given arguments are equal.
*/
public F2 eq() {
return def::equal;
}
/**
* Partially applied equality check.
*
* @param a An object to test for equality against another.
* @return A function that returns true
if the given argument equals the argument to this method.
*/
public F eq(final A a) {
return def.equal(a);
}
/**
* Maps the given function across this equal as a contra-variant functor.
*
* @param f The function to map.
* @return A new equal.
*/
public Equal contramap(final F f) {
return equalDef(contramapDef(f, def));
}
/**
* An equal instance, which reverts equality for self
*
* @return A new equal instance
*/
public final Equal not() {
return equalDef((a1, a2) -> !def.equal(a1, a2));
}
private static Definition contramapDef(F f, Definition aEqDef) {
return new Definition(){
@Override
public F equal(B b) {
return compose(aEqDef.equal(f.f(b)), f);
}
@Override
public boolean equal(B b1, B b2) {
return aEqDef.equal(f.f(b1), f.f(b2));
}
};
}
/**
* Static version of {@link #contramap(F)}
*/
public static Equal contramap(final F f, final Equal eq) {
return eq.contramap(f);
}
/**
* Begin definition of an equal instance.
* @see Definition#then(F, Equal)
*/
public static Definition on(final F f, final Equal eq) {
return contramapDef(f, eq.def);
}
/**
* Constructs an equal instance from the given function.
*
* Java 8+ users: use {@link #equalDef(Definition)} instead.
*
* @param f The function to construct the equal with.
* @return An equal instance from the given function.
*/
public static Equal equal(final F> f) {
return new Equal<>(f::f);
}
/**
* Constructs an equal instance from the given function.
*
* Java 8+ users: use {@link #equalDef(AltDefinition)} instead.
*
* @param f The function to construct the equal with.
* @return An equal instance from the given function.
*/
public static Equal equal(final F2 f) {
return equalDef(f::f);
}
/**
* Constructs an equal instance from the given definition.
*
* @param definition a definition of the equal instance.
* @return An equal instance from the given function.
*/
public static Equal equalDef(final Definition definition) {
return new Equal<>(definition);
}
/**
* Constructs an equal instance from the given (alternative) definition.
*
* @param definition a definition of the equal instance.
* @return An equal instance from the given function.
*/
public static Equal equalDef(final AltDefinition definition) {
return new Equal<>(definition);
}
/**
* Returns an equal instance that uses the {@link Object#equals(Object)} method to test for
* equality.
*
* @return An equal instance that uses the {@link Object#equals(Object)} method to test for
* equality.
*/
public static Equal anyEqual() {
return equalDef(new Definition() {
@Override
public F equal(A a) {
return a::equals;
}
@Override
public boolean equal(A a1, A a2) {
return a1.equals(a2);
}
});
}
/**
* An equal instance for the boolean
type.
*/
public static final Equal booleanEqual = anyEqual();
/**
* An equal instance for the byte
type.
*/
public static final Equal byteEqual = anyEqual();
/**
* An equal instance for the char
type.
*/
public static final Equal charEqual = anyEqual();
/**
* An equal instance for the double
type.
*/
public static final Equal doubleEqual = anyEqual();
/**
* An equal instance for the float
type.
*/
public static final Equal floatEqual = anyEqual();
/**
* An equal instance for the int
type.
*/
public static final Equal intEqual = anyEqual();
/**
* An equal instance for the BigInteger
type.
*/
public static final Equal bigintEqual = anyEqual();
/**
* An equal instance for the BigDecimal
type.
*/
public static final Equal bigdecimalEqual = anyEqual();
/**
* An equal instance for the long
type.
*/
public static final Equal longEqual = anyEqual();
/**
* An equal instance for the short
type.
*/
public static final Equal shortEqual = anyEqual();
/**
* An equal instance for the Natural
type.
*/
public static final Equal naturalEqual = bigintEqual.contramap(Natural::bigIntegerValue);
/**
* An equal instance for the {@link String} type.
*/
public static final Equal stringEqual = anyEqual();
/**
* An equal instance for the {@link StringBuffer} type.
*/
public static final Equal stringBufferEqual =
equalDef((sb1, sb2) -> {
if (sb1.length() == sb2.length()) {
for (int i = 0; i < sb1.length(); i++)
if (sb1.charAt(i) != sb2.charAt(i))
return false;
return true;
} else
return false;
});
/**
* An equal instance for the {@link StringBuilder} type.
*/
public static final Equal stringBuilderEqual =
equalDef((sb1, sb2) -> {
if (sb1.length() == sb2.length()) {
for (int i = 0; i < sb1.length(); i++)
if (sb1.charAt(i) != sb2.charAt(i))
return false;
return true;
} else
return false;
});
/**
* An equal instance for the {@link BitSet} type.
*/
public static final Equal bitSetSequal = equalDef((bs1, bs2) -> bs1.longValue() == bs2.longValue());
/**
* An equal instance for the {@link Either} type.
*
* @param ea Equality across the left side of {@link Either}.
* @param eb Equality across the right side of {@link Either}.
* @return An equal instance for the {@link Either} type.
*/
public static Equal> eitherEqual(final Equal ea, final Equal eb) {
Definition eaDef = ea.def;
Definition ebDef = eb.def;
return equalDef(e1 -> e1.either(
a1 -> Either.either_(eaDef.equal(a1), (B __) -> false),
b1 -> Either.either_((A __)-> false, ebDef.equal(b1))
));
}
public static Equal> resultEqual(final Equal ea, final Equal ei) {
Definition eaDef = ea.def;
Definition eiDef= ei.def;
return equalDef((r1, r2) -> eaDef.equal(r1.value(), r2.value()) && eiDef.equal(r1.rest(), r2.rest()));
}
/**
* An equal instance for the {@link Validation} type.
*
* @param ea Equality across the failing side of {@link Validation}.
* @param eb Equality across the succeeding side of {@link Validation}.
* @return An equal instance for the {@link Validation} type.
*/
public static Equal> validationEqual(final Equal ea, final Equal eb) {
return eitherEqual(ea, eb).contramap(Validation.either());
}
/**
* An equal instance for the {@link List} type.
*
* @param ea Equality across the elements of the list.
* @return An equal instance for the {@link List} type.
*/
public static Equal> listEqual(final Equal ea) {
Definition eaDef = ea.def;
return equalDef((a1, a2) -> {
List x1 = a1;
List x2 = a2;
while (x1.isNotEmpty() && x2.isNotEmpty()) {
if (!eaDef.equal(x1.head(), x2.head()))
return false;
x1 = x1.tail();
x2 = x2.tail();
}
return x1.isEmpty() && x2.isEmpty();
});
}
/**
* An equal instance for the {@link NonEmptyList} type.
*
* @param ea Equality across the elements of the non-empty list.
* @return An equal instance for the {@link NonEmptyList} type.
*/
public static Equal> nonEmptyListEqual(final Equal ea) {
return listEqual(ea).contramap(NonEmptyList.toList_());
}
/**
* An equal instance for the {@link Option} type.
*
* @param ea Equality across the element of the option.
* @return An equal instance for the {@link Option} type.
*/
public static Equal
© 2015 - 2025 Weber Informatics LLC | Privacy Policy