1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.atlassian.fugue;
18
19 import static io.atlassian.fugue.Either.left;
20 import static io.atlassian.fugue.Either.right;
21 import static io.atlassian.fugue.Iterables.concat;
22 import static io.atlassian.fugue.Iterables.drop;
23 import static io.atlassian.fugue.Iterables.first;
24 import static io.atlassian.fugue.Iterables.join;
25 import static io.atlassian.fugue.Iterables.map;
26 import static io.atlassian.fugue.Option.none;
27 import static io.atlassian.fugue.Option.some;
28 import static io.atlassian.fugue.Options.filterNone;
29 import static io.atlassian.fugue.Unit.Unit;
30 import static java.util.Collections.emptyList;
31
32 import java.math.BigInteger;
33 import java.util.ArrayList;
34 import java.util.List;
35 import java.util.function.Function;
36
37
38
39
40
41
42
43 public final class Monoids {
44
45
46
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
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
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
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
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
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
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
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
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
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
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
240
241
242
243
244
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
268
269
270
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
298
299
300
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
320
321
322
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
342
343
344
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
360
361
362
363
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
388
389
390
391
392
393
394
395
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 }