package fj.function; import static fj.Function.*; import fj.F; import fj.Monoid; import fj.Semigroup; import fj.data.List; import fj.data.Stream; import static fj.Semigroup.disjunctionSemigroup; import static fj.Semigroup.conjunctionSemigroup; import static fj.Semigroup.exclusiveDisjunctionSemiGroup; /** * Curried logical functions. * * @version %build.number% */ public final class Booleans { private Booleans() { throw new UnsupportedOperationException(); } /** * Curried form of logical "inclusive or" (disjunction). */ public static final F<Boolean, F<Boolean, Boolean>> or = disjunctionSemigroup.sum(); /** * Curried form of logical "and" (conjunction). */ public static final F<Boolean, F<Boolean, Boolean>> and = conjunctionSemigroup.sum(); /** * Curried form of logical xor (nonequivalence). */ public static final F<Boolean, F<Boolean, Boolean>> xor = exclusiveDisjunctionSemiGroup.sum(); /** * Logical negation. */ public static final F<Boolean, Boolean> not = p -> !p; /** * Curried form of logical "only if" (material implication). */ public static final F<Boolean, F<Boolean, Boolean>> implies = curry((p, q) -> !p || q); /** * Curried form of logical "if" (reverse material implication). */ public static final F<Boolean, F<Boolean, Boolean>> if_ = flip(implies); /** * Curried form of logical "if and only if" (biconditional, equivalence). */ public static final F<Boolean, F<Boolean, Boolean>> iff = compose2(not, xor); /** * Curried form of logical "not implies" (nonimplication). */ public static final F<Boolean, F<Boolean, Boolean>> nimp = compose2(not, implies); /** * Curried form of logical "not if" (reverse nonimplication). */ public static final F<Boolean, F<Boolean, Boolean>> nif = compose2(not, if_); /** * Curried form of logical "not or". */ public static final F<Boolean, F<Boolean, Boolean>> nor = compose2(not, or); /** * Returns true if all the elements of the given list are true. * * @param l A list to check for all the elements being true. * @return true if all the elements of the given list are true. False otherwise. */ public static boolean and(final List<Boolean> l) { return Monoid.conjunctionMonoid.sumLeft(l); } /** * maps given function to the predicate function * @param p predicate to be mapped over * @param f function * @return predicate function */ public static <A, B> F<B, Boolean> contramap(F<B, A> f, F<A, Boolean> p){ return compose(p, f); } /** * alias for contramap * @param p predicate to be mapped over * @param f function * @return predicate function */ public static <A, B> F<B, Boolean> is(F<B, A> f, F<A, Boolean> p){ return contramap(f, p); } /** * returns inverse of contramap * @param p predicate to be mapped over * @param f function * @return predicate function */ public static <A, B> F<B, Boolean> isnot(F<B, A> f, F<A, Boolean> p){ return compose(not, contramap(f, p)); } /** * composes the given predicate using conjunction * @param p1 first predicate * @param p2 second predicate * @return composed predicate function */ public static <A> F<A, Boolean> and(F<A, Boolean> p1, F<A, Boolean> p2){ return Semigroup.<A, Boolean>functionSemigroup(conjunctionSemigroup).sum(p1, p2); } /** * composes the given predicate using exclusive disjunction * @param p1 first predicate * @param p2 second predicate * @return composed predicate function */ public static <A> F<A, Boolean> xor(F<A, Boolean> p1, F<A, Boolean> p2){ return Semigroup.<A, Boolean>functionSemigroup(exclusiveDisjunctionSemiGroup).sum(p1, p2); } /** * returns composed predicate using disjunction * @param p1 first predicate * @param p2 second predicate * @return composed predicate */ public static <A> F<A, Boolean> or(F<A, Boolean> p1, F<A, Boolean> p2){ return Semigroup.<A, Boolean>functionSemigroup(disjunctionSemigroup).sum(p1, p2); } /** * Returns true if all the elements of the given stream are true. * * @param l A stream to check for all the elements being true. * @return true if all the elements of the given stream are true. False otherwise. */ public static boolean and(final Stream<Boolean> l) { return Monoid.conjunctionMonoid.sumLeft(l); } /** * Returns composed predicate * * @param l A stream of predicates * @return composed predicate */ public static <A> F<A, Boolean> andAll(final Stream<F<A, Boolean>> l) { return Monoid.<A, Boolean>functionMonoid(Monoid.conjunctionMonoid).sumLeft(l); } /** * Returns a composed predicate of given List of predicates * * @param l A list of predicate functions * @return composed predicate function */ public static <A> F<A, Boolean> andAll(final List<F<A, Boolean>> l) { return Monoid.<A, Boolean>functionMonoid(Monoid.conjunctionMonoid).sumLeft(l); } /** * Returns a composed predicate of given List of predicates * * @param l A list of predicate functions * @return composed predicate function */ public static <A> F<A, Boolean> orAll(final List<F<A, Boolean>> l) { return Monoid.<A, Boolean>functionMonoid(Monoid.disjunctionMonoid).sumLeft(l); } /** * Returns a composed predicate of given Stream of predicates * * @param l A stream of predicate functions * @return composed predicate function */ public static <A> F<A, Boolean> orAll(final Stream<F<A, Boolean>> l) { return Monoid.<A, Boolean>functionMonoid(Monoid.disjunctionMonoid).sumLeft(l); } /** * Returns true if any element of the given list is true. * * @param l A list to check for any element being true. * @return true if any element of the given list is true. False otherwise. */ public static boolean or(final List<Boolean> l) { return Monoid.disjunctionMonoid.sumLeft(l); } /** * Returns true if any element of the given stream is true. * * @param l A stream to check for any element being true. * @return true if any element of the given stream is true. False otherwise. */ public static boolean or(final Stream<Boolean> l) { return Monoid.disjunctionMonoid.sumLeft(l); } /** * Negates the given predicate. * * @param p A predicate to negate. * @return The negation of the given predicate. */ public static <A> F<A, Boolean> not(final F<A, Boolean> p) { return compose(not, p); } /** * Curried form of conditional. If the first argument is true, returns the second argument, * otherwise the third argument. * * @return A function that returns its second argument if the first argument is true, otherwise the third argument. */ public static <A> F<Boolean, F<A, F<A, A>>> cond() { return curry((p, a1, a2) -> p ? a1 : a2); } }