0
|
1 package fj;
|
|
2
|
|
3 import static fj.Function.curry;
|
|
4
|
|
5 import fj.data.Array;
|
|
6 import fj.data.List;
|
|
7 import fj.data.Natural;
|
|
8 import fj.data.NonEmptyList;
|
|
9 import fj.data.Option;
|
|
10 import fj.data.Set;
|
|
11 import fj.data.Stream;
|
|
12
|
|
13 import java.math.BigInteger;
|
|
14 import java.math.BigDecimal;
|
|
15
|
|
16 /**
|
|
17 * Implementations must satisfy the law of associativity:
|
|
18 * <ul>
|
|
19 * <li><em>Associativity</em>; forall x. forall y. forall z. sum(sum(x, y), z) == sum(x, sum(y, z))</li>
|
|
20 * </ul>
|
|
21 *
|
|
22 * @version %build.number%
|
|
23 */
|
|
24 public final class Semigroup<A> {
|
|
25 private final F<A, F<A, A>> sum;
|
|
26
|
|
27 private Semigroup(final F<A, F<A, A>> sum) {
|
|
28 this.sum = sum;
|
|
29 }
|
|
30
|
|
31 /**
|
|
32 * Sums the two given arguments.
|
|
33 *
|
|
34 * @param a1 A value to sum with another.
|
|
35 * @param a2 A value to sum with another.
|
|
36 * @return The of the two given arguments.
|
|
37 */
|
|
38 public A sum(final A a1, final A a2) {
|
|
39 return sum.f(a1).f(a2);
|
|
40 }
|
|
41
|
|
42 /**
|
|
43 * Returns a function that sums the given value according to this semigroup.
|
|
44 *
|
|
45 * @param a1 The value to sum.
|
|
46 * @return A function that sums the given value according to this semigroup.
|
|
47 */
|
|
48 public F<A, A> sum(final A a1) {
|
|
49 return sum.f(a1);
|
|
50 }
|
|
51
|
|
52 /**
|
|
53 * Returns a function that sums according to this semigroup.
|
|
54 *
|
|
55 * @return A function that sums according to this semigroup.
|
|
56 */
|
|
57 public F<A, F<A, A>> sum() {
|
|
58 return sum;
|
|
59 }
|
|
60
|
|
61 /**
|
|
62 * Constructs a semigroup from the given function.
|
|
63 *
|
|
64 * @param sum The function to construct this semigroup with.
|
|
65 * @return A semigroup from the given function.
|
|
66 */
|
|
67 public static <A> Semigroup<A> semigroup(final F<A, F<A, A>> sum) {
|
|
68 return new Semigroup<A>(sum);
|
|
69 }
|
|
70
|
|
71 /**
|
|
72 * Constructs a semigroup from the given function.
|
|
73 *
|
|
74 * @param sum The function to construct this semigroup with.
|
|
75 * @return A semigroup from the given function.
|
|
76 */
|
|
77 public static <A> Semigroup<A> semigroup(final F2<A, A, A> sum) {
|
|
78 return new Semigroup<A>(curry(sum));
|
|
79 }
|
|
80
|
|
81 /**
|
|
82 * A semigroup that adds integers.
|
|
83 */
|
|
84 public static final Semigroup<Integer> intAdditionSemigroup = semigroup(new F2<Integer, Integer, Integer>() {
|
|
85 public Integer f(final Integer i1, final Integer i2) {
|
|
86 return i1 + i2;
|
|
87 }
|
|
88 });
|
|
89
|
|
90 /**
|
|
91 * A semigroup that adds doubles.
|
|
92 */
|
|
93 public static final Semigroup<Double> doubleAdditionSemigroup = semigroup(new F2<Double, Double, Double>() {
|
|
94 public Double f(final Double d1, final Double d2) {
|
|
95 return d1 + d2;
|
|
96 }
|
|
97 });
|
|
98
|
|
99 /**
|
|
100 * A semigroup that multiplies integers.
|
|
101 */
|
|
102 public static final Semigroup<Integer> intMultiplicationSemigroup = semigroup(new F2<Integer, Integer, Integer>() {
|
|
103 public Integer f(final Integer i1, final Integer i2) {
|
|
104 return i1 * i2;
|
|
105 }
|
|
106 });
|
|
107
|
|
108 /**
|
|
109 * A semigroup that multiplies doubles.
|
|
110 */
|
|
111 public static final Semigroup<Double> doubleMultiplicationSemigroup = semigroup(new F2<Double, Double, Double>() {
|
|
112 public Double f(final Double d1, final Double d2) {
|
|
113 return d1 * d2;
|
|
114 }
|
|
115 });
|
|
116
|
|
117 /**
|
|
118 * A semigroup that yields the maximum of integers.
|
|
119 */
|
|
120 public static final Semigroup<Integer> intMaximumSemigroup = semigroup(Ord.intOrd.max);
|
|
121
|
|
122 /**
|
|
123 * A semigroup that yields the minimum of integers.
|
|
124 */
|
|
125 public static final Semigroup<Integer> intMinimumSemigroup = semigroup(Ord.intOrd.min);
|
|
126
|
|
127 /**
|
|
128 * A semigroup that adds big integers.
|
|
129 */
|
|
130 public static final Semigroup<BigInteger> bigintAdditionSemigroup =
|
|
131 semigroup(new F2<BigInteger, BigInteger, BigInteger>() {
|
|
132 public BigInteger f(final BigInteger i1, final BigInteger i2) {
|
|
133 return i1.add(i2);
|
|
134 }
|
|
135 });
|
|
136
|
|
137 /**
|
|
138 * A semigroup that multiplies big integers.
|
|
139 */
|
|
140 public static final Semigroup<BigInteger> bigintMultiplicationSemigroup =
|
|
141 semigroup(new F2<BigInteger, BigInteger, BigInteger>() {
|
|
142 public BigInteger f(final BigInteger i1, final BigInteger i2) {
|
|
143 return i1.multiply(i2);
|
|
144 }
|
|
145 });
|
|
146
|
|
147 /**
|
|
148 * A semigroup that yields the maximum of big integers.
|
|
149 */
|
|
150 public static final Semigroup<BigInteger> bigintMaximumSemigroup = semigroup(Ord.bigintOrd.max);
|
|
151
|
|
152 /**
|
|
153 * A semigroup that yields the minimum of big integers.
|
|
154 */
|
|
155 public static final Semigroup<BigInteger> bigintMinimumSemigroup = semigroup(Ord.bigintOrd.min);
|
|
156
|
|
157 /**
|
|
158 * A semigroup that adds big decimals.
|
|
159 */
|
|
160 public static final Semigroup<BigDecimal> bigdecimalAdditionSemigroup =
|
|
161 semigroup(new F2<BigDecimal, BigDecimal, BigDecimal>() {
|
|
162 public BigDecimal f(final BigDecimal i1, final BigDecimal i2) {
|
|
163 return i1.add(i2);
|
|
164 }
|
|
165 });
|
|
166
|
|
167 /**
|
|
168 * A semigroup that multiplies big decimals.
|
|
169 */
|
|
170 public static final Semigroup<BigDecimal> bigdecimalMultiplicationSemigroup =
|
|
171 semigroup(new F2<BigDecimal, BigDecimal, BigDecimal>() {
|
|
172 public BigDecimal f(final BigDecimal i1, final BigDecimal i2) {
|
|
173 return i1.multiply(i2);
|
|
174 }
|
|
175 });
|
|
176
|
|
177 /**
|
|
178 * A semigroup that yields the maximum of big decimals.
|
|
179 */
|
|
180 public static final Semigroup<BigDecimal> bigDecimalMaximumSemigroup = semigroup(Ord.bigdecimalOrd.max);
|
|
181
|
|
182 /**
|
|
183 * A semigroup that yields the minimum of big decimals.
|
|
184 */
|
|
185 public static final Semigroup<BigDecimal> bigDecimalMinimumSemigroup = semigroup(Ord.bigdecimalOrd.min);
|
|
186
|
|
187 /**
|
|
188 * A semigroup that multiplies natural numbers.
|
|
189 */
|
|
190 public static final Semigroup<Natural> naturalMultiplicationSemigroup =
|
|
191 semigroup(new F2<Natural, Natural, Natural>() {
|
|
192 public Natural f(final Natural n1, final Natural n2) {
|
|
193 return n1.multiply(n2);
|
|
194 }
|
|
195 });
|
|
196
|
|
197 /**
|
|
198 * A semigroup that multiplies natural numbers.
|
|
199 */
|
|
200 public static final Semigroup<Natural> naturalAdditionSemigroup =
|
|
201 semigroup(new F2<Natural, Natural, Natural>() {
|
|
202 public Natural f(final Natural n1, final Natural n2) {
|
|
203 return n1.add(n2);
|
|
204 }
|
|
205 });
|
|
206
|
|
207 /**
|
|
208 * A semigroup that yields the maximum of natural numbers.
|
|
209 */
|
|
210 public static final Semigroup<Natural> naturalMaximumSemigroup = semigroup(Ord.naturalOrd.max);
|
|
211
|
|
212 /**
|
|
213 * A semigroup that yields the minimum of natural numbers.
|
|
214 */
|
|
215 public static final Semigroup<Natural> naturalMinimumSemigroup = semigroup(Ord.naturalOrd.min);
|
|
216
|
|
217 /**
|
|
218 * A semigroup that adds longs.
|
|
219 */
|
|
220 public static final Semigroup<Long> longAdditionSemigroup = semigroup(new F2<Long, Long, Long>() {
|
|
221 public Long f(final Long x, final Long y) {
|
|
222 return x + y;
|
|
223 }
|
|
224 });
|
|
225
|
|
226 /**
|
|
227 * A semigroup that multiplies longs.
|
|
228 */
|
|
229 public static final Semigroup<Long> longMultiplicationSemigroup = semigroup(new F2<Long, Long, Long>() {
|
|
230 public Long f(final Long x, final Long y) {
|
|
231 return x * y;
|
|
232 }
|
|
233 });
|
|
234
|
|
235 /**
|
|
236 * A semigroup that yields the maximum of longs.
|
|
237 */
|
|
238 public static final Semigroup<Long> longMaximumSemigroup = semigroup(Ord.longOrd.max);
|
|
239
|
|
240 /**
|
|
241 * A semigroup that yields the minimum of longs.
|
|
242 */
|
|
243 public static final Semigroup<Long> longMinimumSemigroup = semigroup(Ord.longOrd.min);
|
|
244
|
|
245 /**
|
|
246 * A semigroup that ORs booleans.
|
|
247 */
|
|
248 public static final Semigroup<Boolean> disjunctionSemigroup = semigroup(new F2<Boolean, Boolean, Boolean>() {
|
|
249 public Boolean f(final Boolean b1, final Boolean b2) {
|
|
250 return b1 || b2;
|
|
251 }
|
|
252 });
|
|
253
|
|
254 /**
|
|
255 * A semigroup that XORs booleans.
|
|
256 */
|
|
257 public static final Semigroup<Boolean> exclusiveDisjunctionSemiGroup = semigroup(new F2<Boolean, Boolean, Boolean>() {
|
|
258 public Boolean f(final Boolean p, final Boolean q) {
|
|
259 return p && !q || !p && q;
|
|
260 }
|
|
261 });
|
|
262
|
|
263 /**
|
|
264 * A semigroup that ANDs booleans.
|
|
265 */
|
|
266 public static final Semigroup<Boolean> conjunctionSemigroup = semigroup(new F2<Boolean, Boolean, Boolean>() {
|
|
267 public Boolean f(final Boolean b1, final Boolean b2) {
|
|
268 return b1 && b2;
|
|
269 }
|
|
270 });
|
|
271
|
|
272 /**
|
|
273 * A semigroup that appends strings.
|
|
274 */
|
|
275 public static final Semigroup<String> stringSemigroup = semigroup(new F2<String, String, String>() {
|
|
276 public String f(final String s1, final String s2) {
|
|
277 return s1 + s2;
|
|
278 }
|
|
279 });
|
|
280
|
|
281 /**
|
|
282 * A semigroup that appends string buffers.
|
|
283 */
|
|
284 public static final Semigroup<StringBuffer> stringBufferSemigroup =
|
|
285 semigroup(new F2<StringBuffer, StringBuffer, StringBuffer>() {
|
|
286 public StringBuffer f(final StringBuffer s1, final StringBuffer s2) {
|
|
287 return new StringBuffer(s1).append(s2);
|
|
288 }
|
|
289 });
|
|
290
|
|
291 /**
|
|
292 * A semigroup that appends string builders.
|
|
293 */
|
|
294 public static final Semigroup<StringBuilder> stringBuilderSemigroup =
|
|
295 semigroup(new F2<StringBuilder, StringBuilder, StringBuilder>() {
|
|
296 public StringBuilder f(final StringBuilder s1, final StringBuilder s2) {
|
|
297 return new StringBuilder(s1).append(s2);
|
|
298 }
|
|
299 });
|
|
300
|
|
301 /**
|
|
302 * A semigroup for functions.
|
|
303 *
|
|
304 * @param sb The smeigroup for the codomain.
|
|
305 * @return A semigroup for functions.
|
|
306 */
|
|
307 public static <A, B> Semigroup<F<A, B>> functionSemigroup(final Semigroup<B> sb) {
|
|
308 return semigroup(new F2<F<A, B>, F<A, B>, F<A, B>>() {
|
|
309 public F<A, B> f(final F<A, B> a1, final F<A, B> a2) {
|
|
310 return new F<A, B>() {
|
|
311 public B f(final A a) {
|
|
312 return sb.sum(a1.f(a), a2.f(a));
|
|
313 }
|
|
314 };
|
|
315 }
|
|
316 });
|
|
317 }
|
|
318
|
|
319 /**
|
|
320 * A semigroup for lists.
|
|
321 *
|
|
322 * @return A semigroup for lists.
|
|
323 */
|
|
324 public static <A> Semigroup<List<A>> listSemigroup() {
|
|
325 return semigroup(new F2<List<A>, List<A>, List<A>>() {
|
|
326 public List<A> f(final List<A> a1, final List<A> a2) {
|
|
327 return a1.append(a2);
|
|
328 }
|
|
329 });
|
|
330 }
|
|
331
|
|
332 /**
|
|
333 * A semigroup for non-empty lists.
|
|
334 *
|
|
335 * @return A semigroup for non-empty lists.
|
|
336 */
|
|
337 public static <A> Semigroup<NonEmptyList<A>> nonEmptyListSemigroup() {
|
|
338 return semigroup(new F2<NonEmptyList<A>, NonEmptyList<A>, NonEmptyList<A>>() {
|
|
339 public NonEmptyList<A> f(final NonEmptyList<A> a1, final NonEmptyList<A> a2) {
|
|
340 return a1.append(a2);
|
|
341 }
|
|
342 });
|
|
343 }
|
|
344
|
|
345 /**
|
|
346 * A semigroup for optional values.
|
|
347 ** @return A semigroup for optional values.
|
|
348 */
|
|
349 public static <A> Semigroup<Option<A>> optionSemigroup() {
|
|
350 return semigroup(new F2<Option<A>, Option<A>, Option<A>>() {
|
|
351 public Option<A> f(final Option<A> a1, final Option<A> a2) {
|
|
352 return a1.isSome() ? a1 : a2;
|
|
353 }
|
|
354 });
|
|
355 }
|
|
356
|
|
357 /**
|
|
358 * A semigroup for optional values that take the first available value.
|
|
359 *
|
|
360 * @return A semigroup for optional values that take the first available value.
|
|
361 */
|
|
362 public static <A> Semigroup<Option<A>> firstOptionSemigroup() {
|
|
363 return semigroup(new F2<Option<A>, Option<A>, Option<A>>() {
|
|
364 public Option<A> f(final Option<A> a1, final Option<A> a2) {
|
|
365 return a1.orElse(a2);
|
|
366 }
|
|
367 });
|
|
368 }
|
|
369
|
|
370 /**
|
|
371 * A semigroup for optional values that take the last available value.
|
|
372 *
|
|
373 * @return A semigroup for optional values that take the last available value.
|
|
374 */
|
|
375 public static <A> Semigroup<Option<A>> lastOptionSemigroup() {
|
|
376 return semigroup(new F2<Option<A>, Option<A>, Option<A>>() {
|
|
377 public Option<A> f(final Option<A> a1, final Option<A> a2) {
|
|
378 return a2.orElse(a1);
|
|
379 }
|
|
380 });
|
|
381 }
|
|
382
|
|
383 /**
|
|
384 * A semigroup for streams.
|
|
385 *
|
|
386 * @return A semigroup for streams.
|
|
387 */
|
|
388 public static <A> Semigroup<Stream<A>> streamSemigroup() {
|
|
389 return semigroup(new F2<Stream<A>, Stream<A>, Stream<A>>() {
|
|
390 public Stream<A> f(final Stream<A> a1, final Stream<A> a2) {
|
|
391 return a1.append(a2);
|
|
392 }
|
|
393 });
|
|
394 }
|
|
395
|
|
396 /**
|
|
397 * A semigroup for arrays.
|
|
398 *
|
|
399 * @return A semigroup for arrays.
|
|
400 */
|
|
401 public static <A> Semigroup<Array<A>> arraySemigroup() {
|
|
402 return semigroup(new F2<Array<A>, Array<A>, Array<A>>() {
|
|
403 public Array<A> f(final Array<A> a1, final Array<A> a2) {
|
|
404 return a1.append(a2);
|
|
405 }
|
|
406 });
|
|
407 }
|
|
408
|
|
409 /**
|
|
410 * A semigroup for unary products.
|
|
411 *
|
|
412 * @param sa A semigroup for the product's type.
|
|
413 * @return A semigroup for unary products.
|
|
414 */
|
|
415 public static <A> Semigroup<P1<A>> p1Semigroup(final Semigroup<A> sa) {
|
|
416 return semigroup(new F2<P1<A>, P1<A>, P1<A>>() {
|
|
417 public P1<A> f(final P1<A> a1, final P1<A> a2) {
|
|
418 return new P1<A>() {
|
|
419 public A _1() {
|
|
420 return sa.sum(a1._1(), a2._1());
|
|
421 }
|
|
422 };
|
|
423 }
|
|
424 });
|
|
425 }
|
|
426
|
|
427 /**
|
|
428 * A semigroup for binary products.
|
|
429 *
|
|
430 * @param sa A semigroup for the product's first type.
|
|
431 * @param sb A semigroup for the product's second type.
|
|
432 * @return A semigroup for binary products.
|
|
433 */
|
|
434 public static <A, B> Semigroup<P2<A, B>> p2Semigroup(final Semigroup<A> sa, final Semigroup<B> sb) {
|
|
435 return semigroup(new F2<P2<A, B>, P2<A, B>, P2<A, B>>() {
|
|
436 public P2<A, B> f(final P2<A, B> a1, final P2<A, B> a2) {
|
|
437 return new P2<A, B>() {
|
|
438 public A _1() {
|
|
439 return sa.sum(a1._1(), a2._1());
|
|
440 }
|
|
441
|
|
442 public B _2() {
|
|
443 return sb.sum(a1._2(), a2._2());
|
|
444 }
|
|
445 };
|
|
446 }
|
|
447 });
|
|
448 }
|
|
449
|
|
450 /**
|
|
451 * A semigroup for the Unit value.
|
|
452 */
|
|
453 public static final Semigroup<Unit> unitSemigroup = semigroup(new F2<Unit, Unit, Unit>() {
|
|
454 public Unit f(final Unit u1, final Unit u2) {
|
|
455 return Unit.unit();
|
|
456 }
|
|
457 });
|
|
458
|
|
459 /**
|
|
460 * A semigroup for sets.
|
|
461 *
|
|
462 * @return a semigroup for sets.
|
|
463 */
|
|
464 public static <A> Semigroup<Set<A>> setSemigroup() {
|
|
465 return semigroup(new F2<Set<A>, Set<A>, Set<A>>() {
|
|
466 public Set<A> f(final Set<A> a, final Set<A> b) {
|
|
467 return a.union(b);
|
|
468 }
|
|
469 });
|
|
470 }
|
|
471
|
|
472 }
|