View Javadoc
1   /*
2      Copyright 2015 Atlassian
3   
4      Licensed under the Apache License, Version 2.0 (the "License");
5      you may not use this file except in compliance with the License.
6      You may obtain a copy of the License at
7   
8          http://www.apache.org/licenses/LICENSE-2.0
9   
10     Unless required by applicable law or agreed to in writing, software
11     distributed under the License is distributed on an "AS IS" BASIS,
12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13     See the License for the specific language governing permissions and
14     limitations under the License.
15   */
16  
17  package io.atlassian.fugue;
18  
19  import java.math.BigInteger;
20  import java.util.ArrayList;
21  import java.util.List;
22  import java.util.function.Function;
23  
24  import static io.atlassian.fugue.Either.left;
25  import static io.atlassian.fugue.Either.right;
26  import static io.atlassian.fugue.Iterables.concat;
27  import static io.atlassian.fugue.Iterables.drop;
28  import static io.atlassian.fugue.Iterables.first;
29  import static io.atlassian.fugue.Iterables.join;
30  import static io.atlassian.fugue.Iterables.map;
31  import static io.atlassian.fugue.Option.none;
32  import static io.atlassian.fugue.Option.some;
33  import static io.atlassian.fugue.Options.filterNone;
34  import static io.atlassian.fugue.Unit.Unit;
35  import static java.util.Collections.emptyList;
36  
37  /**
38   * {@link io.atlassian.fugue.Monoid} instances.
39   *
40   * @see Semigroups
41   * @since 3.0
42   */
43  public final class Monoids {
44  
45    /**
46     * A monoid that adds integers.
47     */
48    public static final Monoid<Integer> intAddition = new Monoid<Integer>() {
49      @Override public Integer append(final Integer i1, final Integer i2) {
50        return i1 + i2;
51      }
52  
53      @Override public Integer zero() {
54        return 0;
55      }
56  
57      @Override public Integer multiply(final int n, final Integer i) {
58        return n <= 0 ? 0 : n * i;
59      }
60    };
61  
62    /**
63     * A monoid that multiplies integers.
64     */
65    public static final Monoid<Integer> intMultiplication = new Monoid<Integer>() {
66      @Override public Integer append(final Integer i1, final Integer i2) {
67        return i1 * i2;
68      }
69  
70      @Override public Integer zero() {
71        return 1;
72      }
73    };
74  
75    /**
76     * A monoid that adds big integers.
77     */
78    public static final Monoid<BigInteger> bigintAddition = new Monoid<BigInteger>() {
79      @Override public BigInteger append(final BigInteger a1, final BigInteger a2) {
80        return a1.add(a2);
81      }
82  
83      @Override public BigInteger zero() {
84        return BigInteger.ZERO;
85      }
86  
87      @Override public BigInteger multiply(final int n, final BigInteger b) {
88        return n <= 0 ? BigInteger.ZERO : b.multiply(BigInteger.valueOf(n));
89      }
90    };
91  
92    /**
93     * A monoid that multiplies big integers.
94     */
95    public static final Monoid<BigInteger> bigintMultiplication = new Monoid<BigInteger>() {
96      @Override public BigInteger append(final BigInteger a1, final BigInteger a2) {
97        return a1.multiply(a2);
98      }
99  
100     @Override public BigInteger zero() {
101       return BigInteger.ONE;
102     }
103 
104     @Override public BigInteger multiply(final int n, final BigInteger b) {
105       return n <= 0 ? BigInteger.ONE : b.pow(n);
106     }
107   };
108 
109   /**
110    * A monoid that adds longs.
111    */
112   public static final Monoid<Long> longAddition = new Monoid<Long>() {
113     @Override public Long append(final Long a1, final Long a2) {
114       return a1 + a2;
115     }
116 
117     @Override public Long zero() {
118       return 0L;
119     }
120 
121     @Override public Long multiply(final int n, final Long l) {
122       return n <= 0 ? 0L : l * n;
123     }
124   };
125 
126   /**
127    * A monoid that multiplies longs.
128    */
129   public static final Monoid<Long> longMultiplication = new Monoid<Long>() {
130     @Override public Long append(final Long a1, final Long a2) {
131       return a1 * a2;
132     }
133 
134     @Override public Long zero() {
135       return 1L;
136     }
137   };
138 
139   /**
140    * A monoid that ORs booleans.
141    */
142   public static final Monoid<Boolean> disjunction = new Monoid<Boolean>() {
143     @Override public Boolean append(final Boolean a1, final Boolean a2) {
144       return a1 || a2;
145     }
146 
147     @Override public Boolean zero() {
148       return false;
149     }
150 
151     @Override public Boolean sum(final Iterable<Boolean> bs) {
152       return Iterables.filter(bs, b -> b).iterator().hasNext();
153     }
154 
155     @Override public Boolean multiply(final int n, final Boolean b) {
156       return n <= 0 ? false : b;
157     }
158   };
159 
160   /**
161    * A monoid that XORs booleans.
162    */
163   public static final Monoid<Boolean> exclusiveDisjunction = new Monoid<Boolean>() {
164     @Override public Boolean append(final Boolean a1, final Boolean a2) {
165       return (a1 ^ a2);
166     }
167 
168     @Override public Boolean zero() {
169       return false;
170     }
171 
172     @Override public Boolean multiply(final int n, final Boolean b) {
173       return b && (n == 1);
174     }
175   };
176 
177   /**
178    * A monoid that ANDs booleans.
179    */
180   public static final Monoid<Boolean> conjunction = new Monoid<Boolean>() {
181     @Override public Boolean append(final Boolean a1, final Boolean a2) {
182       return a1 && a2;
183     }
184 
185     @Override public Boolean zero() {
186       return true;
187     }
188 
189     @Override public Boolean sum(final Iterable<Boolean> bs) {
190       return !Iterables.filter(bs, b -> !b).iterator().hasNext();
191     }
192   };
193 
194   /**
195    * A monoid that appends strings.
196    */
197   public static final Monoid<String> string = new Monoid<String>() {
198     @Override public String append(final String a1, final String a2) {
199       return a1.concat(a2);
200     }
201 
202     @Override public String zero() {
203       return "";
204     }
205 
206     @Override public String sum(final Iterable<String> ss) {
207       final StringBuilder sb = new StringBuilder();
208       for (final String s : ss) {
209         sb.append(s);
210       }
211       return sb.toString();
212     }
213   };
214 
215   /**
216    * A monoid for the Unit value.
217    */
218   public static final Monoid<Unit> unit = new Monoid<Unit>() {
219     @Override public Unit append(final Unit a1, final Unit a2) {
220       return Unit();
221     }
222 
223     @Override public Unit zero() {
224       return Unit();
225     }
226 
227     @Override public Unit multiply(final int n, final Unit unit) {
228       return Unit();
229     }
230 
231     @Override public Unit multiply1p(final int n, final Unit unit) {
232       return Unit();
233     }
234   };
235 
236   private Monoids() {}
237 
238   /**
239    * A monoid for functions.
240    *
241    * @param <A> input type
242    * @param <B> composable output type
243    * @param mb The monoid for the function codomain.
244    * @return A monoid for functions.
245    */
246   public static <A, B> Monoid<Function<A, B>> function(final Monoid<B> mb) {
247     return new Monoid<Function<A, B>>() {
248       @Override public Function<A, B> append(final Function<A, B> a1, final Function<A, B> a2) {
249         return a -> mb.append(a1.apply(a), a2.apply(a));
250       }
251 
252       @Override public Function<A, B> zero() {
253         return a -> mb.zero();
254       }
255 
256       @Override public Function<A, B> sum(final Iterable<Function<A, B>> fs) {
257         return a -> mb.sum(map(fs, Functions.<A, B> apply(a)));
258       }
259 
260       @Override public Function<A, B> multiply(final int n, final Function<A, B> f) {
261         return a -> mb.multiply(n, f.apply(a));
262       }
263     };
264   }
265 
266   /**
267    * A monoid for lists.
268    *
269    * @param <A> internal type
270    * @return A monoid for lists.
271    */
272   public static <A> Monoid<List<A>> list() {
273     return new Monoid<List<A>>() {
274       @Override public List<A> append(final List<A> l1, final List<A> l2) {
275         final List<A> sumList;
276         if (l1.isEmpty()) {
277           sumList = l2;
278 
279         } else if (l2.isEmpty()) {
280           sumList = l1;
281 
282         } else {
283           sumList = new ArrayList<>(l1.size() + l2.size());
284           sumList.addAll(l1);
285           sumList.addAll(l2);
286         }
287         return sumList;
288       }
289 
290       @Override public List<A> zero() {
291         return emptyList();
292       }
293     };
294   }
295 
296   /**
297    * A monoid for iterables.
298    *
299    * @param <A> internal type
300    * @return A monoid for iterables.
301    */
302   public static <A> Monoid<Iterable<A>> iterable() {
303     return new Monoid<Iterable<A>>() {
304       @Override public Iterable<A> append(final Iterable<A> a1, final Iterable<A> a2) {
305         return concat(a1, a2);
306       }
307 
308       @Override public Iterable<A> zero() {
309         return emptyList();
310       }
311 
312       @Override public Iterable<A> sum(final Iterable<Iterable<A>> iterable) {
313         return join(iterable);
314       }
315     };
316   }
317 
318   /**
319    * A monoid for options (that take the first available value).
320    *
321    * @param <A> internal type
322    * @return A monoid for options (that take the first available value).
323    */
324   public static <A> Monoid<Option<A>> firstOption() {
325     return new Monoid<Option<A>>() {
326       @Override public Option<A> append(final Option<A> a1, final Option<A> a2) {
327         return a1.isDefined() ? a1 : a2;
328       }
329 
330       @Override public Option<A> zero() {
331         return none();
332       }
333 
334       @Override public Option<A> sum(final Iterable<Option<A>> os) {
335         return first(filterNone(os)).getOrElse(none());
336       }
337     };
338   }
339 
340   /**
341    * A monoid for options that take the last available value.
342    *
343    * @param <A> internal type
344    * @return A monoid for options that take the last available value.
345    */
346   public static <A> Monoid<Option<A>> lastOption() {
347     return new Monoid<Option<A>>() {
348       @Override public Option<A> append(final Option<A> a1, final Option<A> a2) {
349         return a2.isDefined() ? a2 : a1;
350       }
351 
352       @Override public Option<A> zero() {
353         return none();
354       }
355     };
356   }
357 
358   /**
359    * A monoid for options that combine inner value with a semigroup.
360    *
361    * @param <A> internal type
362    * @return A monoid for options that combine inner value with a semigroup.
363    * @param semigroup a {@link io.atlassian.fugue.Semigroup} object.
364    */
365   public static <A> Monoid<Option<A>> option(final Semigroup<A> semigroup) {
366     return new Monoid<Option<A>>() {
367       @Override public Option<A> append(final Option<A> o1, final Option<A> o2) {
368         return o1.fold(() -> o2, a1 -> o2.fold(() -> o1, a2 -> some(semigroup.append(a1, a2))));
369       }
370 
371       @Override public Option<A> zero() {
372         return none();
373       }
374 
375       @Override public Option<A> sum(final Iterable<Option<A>> os) {
376         final Iterable<A> memoized = Iterables.memoize(Options.flatten(os));
377         return first(memoized).fold(Option::<A> none, a -> some(semigroup.sumNonEmpty(a, drop(1, memoized))));
378       }
379 
380       @Override public Option<A> multiply(final int n, final Option<A> as) {
381         return n <= 0 ? none() : as.fold(Option::<A> none, a -> some(semigroup.multiply1p(n - 1, a)));
382       }
383     };
384   }
385 
386   /**
387    * A monoid Sums up values inside either
388    * {@link io.atlassian.fugue.Semigroups#either}. Monoid of right values
389    * provide the identity element of the resulting monoid.
390    *
391    * @param <L> desired left type
392    * @param <R> desired right type
393    * @param lS semigroup for left values
394    * @param rM monoid for right values.
395    * @return A monoid Sums up values inside either.
396    */
397   public static <L, R> Monoid<Either<L, R>> either(final Semigroup<L> lS, final Monoid<R> rM) {
398     final Either<L, R> zero = right(rM.zero());
399     return new Monoid<Either<L, R>>() {
400 
401       @Override public Either<L, R> append(final Either<L, R> e1, final Either<L, R> e2) {
402         return e1.<Either<L, R>> fold(l1 -> e2.<Either<L, R>> fold(l2 -> left(lS.append(l1, l2)), r2 -> e1),
403           r1 -> e2.<Either<L, R>> fold(l2 -> e2, r2 -> right(rM.append(r1, r2))));
404       }
405 
406       @Override public Either<L, R> zero() {
407         return zero;
408       }
409     };
410   }
411 
412 }