001    package fj.function;
002    
003    import fj.F;
004    import fj.F2;
005    import fj.F3;
006    import static fj.Function.*;
007    import fj.data.List;
008    import fj.data.Stream;
009    import fj.pre.Monoid;
010    import static fj.pre.Semigroup.disjunctionSemigroup;
011    import static fj.pre.Semigroup.conjunctionSemigroup;
012    import static fj.pre.Semigroup.exclusiveDisjunctionSemiGroup;
013    
014    /**
015     * Curried logical functions.
016     *
017     * @version %build.number%<br>
018     *          <ul>
019     *          <li>$LastChangedRevision: 143 $</li>
020     *          <li>$LastChangedDate: 2009-05-22 03:56:25 +1000 (Fri, 22 May 2009) $</li>
021     *          </ul>
022     */
023    public final class Booleans {
024      private Booleans() {
025        throw new UnsupportedOperationException();
026      }
027    
028      /**
029       * Curried form of logical "inclusive or" (disjunction).
030       */
031      public static final F<Boolean, F<Boolean, Boolean>> or = disjunctionSemigroup.sum();
032    
033      /**
034       * Curried form of logical "and" (conjunction).
035       */
036      public static final F<Boolean, F<Boolean, Boolean>> and = conjunctionSemigroup.sum();
037    
038    
039      /**
040       * Curried form of logical xor (nonequivalence).
041       */
042      public static final F<Boolean, F<Boolean, Boolean>> xor = exclusiveDisjunctionSemiGroup.sum();
043    
044      /**
045       * Logical negation.
046       */
047      public static final F<Boolean, Boolean> not = new F<Boolean, Boolean>() {
048        public Boolean f(final Boolean p) {
049          return !p;
050        }
051      };
052    
053      /**
054       * Curried form of logical "only if" (material implication).
055       */
056      public static final F<Boolean, F<Boolean, Boolean>> implies = curry(new F2<Boolean, Boolean, Boolean>() {
057        public Boolean f(final Boolean p, final Boolean q) {
058          return !p || q;
059        }
060      });
061    
062      /**
063       * Curried form of logical "if" (reverse material implication).
064       */
065      public static final F<Boolean, F<Boolean, Boolean>> if_ = flip(implies);
066    
067      /**
068       * Curried form of logical "if and only if" (biconditional, equivalence).
069       */
070      public static final F<Boolean, F<Boolean, Boolean>> iff = compose2(not, xor);
071    
072      /**
073       * Curried form of logical "not implies" (nonimplication).
074       */
075      public static final F<Boolean, F<Boolean, Boolean>> nimp = compose2(not, implies);
076    
077      /**
078       * Curried form of logical "not if" (reverse nonimplication).
079       */
080      public static final F<Boolean, F<Boolean, Boolean>> nif = compose2(not, if_);
081    
082      /**
083       * Curried form of logical "not or".
084       */
085      public static final F<Boolean, F<Boolean, Boolean>> nor = compose2(not, or);
086    
087      /**
088       * Returns true if all the elements of the given list are true.
089       *
090       * @param l A list to check for all the elements being true.
091       * @return true if all the elements of the given list are true. False otherwise.
092       */
093      public static boolean and(final List<Boolean> l) {
094        return Monoid.conjunctionMonoid.sumLeft(l);
095      }
096    
097      /**
098       * Returns true if all the elements of the given stream are true.
099       *
100       * @param l A stream to check for all the elements being true.
101       * @return true if all the elements of the given stream are true. False otherwise.
102       */
103      public static boolean and(final Stream<Boolean> l) {
104        return Monoid.conjunctionMonoid.sumLeft(l);
105      }
106    
107      /**
108       * Returns true if any element of the given list is true.
109       *
110       * @param l A list to check for any element being true.
111       * @return true if any element of the given list is true. False otherwise.
112       */
113      public static boolean or(final List<Boolean> l) {
114        return Monoid.disjunctionMonoid.sumLeft(l);
115      }
116    
117      /**
118       * Returns true if any element of the given stream is true.
119       *
120       * @param l A stream to check for any element being true.
121       * @return true if any element of the given stream is true. False otherwise.
122       */
123      public static boolean or(final Stream<Boolean> l) {
124        return Monoid.disjunctionMonoid.sumLeft(l);
125      }
126    
127      /**
128       * Negates the given predicate.
129       *
130       * @param p A predicate to negate.
131       * @return The negation of the given predicate.
132       */
133      public static <A> F<A, Boolean> not(final F<A, Boolean> p) {
134        return compose(not, p);
135      }
136    
137      /**
138       * Curried form of conditional. If the first argument is true, returns the second argument,
139       * otherwise the third argument.
140       *
141       * @return A function that returns its second argument if the first argument is true, otherwise the third argument.
142       */
143      public static <A> F<Boolean, F<A, F<A, A>>> cond() {
144        return curry(new F3<Boolean, A, A, A>() {
145          public A f(final Boolean p, final A a1, final A a2) {
146            return p ? a1 : a2;
147          }
148        });
149      }
150    }