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.BigDecimal;
20 import java.math.BigInteger;
21 import java.util.Comparator;
22 import java.util.function.Function;
23
24 import static io.atlassian.fugue.Either.left;
25 import static io.atlassian.fugue.Either.right;
26
27 /**
28 * {@link io.atlassian.fugue.Semigroup} instances.
29 *
30 * @see Monoids
31 * @since 3.1
32 */
33 public final class Semigroups {
34
35 /**
36 * A semigroup that yields the maximum of integers.
37 */
38 public static final Semigroup<Integer> intMaximum = Math::max;
39
40 /**
41 * A semigroup that yields the minimum of integers.
42 */
43 public static final Semigroup<Integer> intMinimum = Math::min;
44
45 /**
46 * A semigroup that yields the maximum of big integers.
47 */
48 public static final Semigroup<BigInteger> bigintMaximum = BigInteger::max;
49
50 /**
51 * A semigroup that yields the minimum of big integers.
52 */
53 public static final Semigroup<BigInteger> bigintMinimum = BigInteger::min;
54
55 /**
56 * A semigroup that yields the maximum of big decimals.
57 */
58 public static final Semigroup<BigDecimal> bigDecimalMaximum = BigDecimal::max;
59
60 /**
61 * A semigroup that yields the minimum of big decimals.
62 */
63 public static final Semigroup<BigDecimal> bigDecimalMinimum = BigDecimal::min;
64
65 /**
66 * A semigroup that yields the maximum of longs.
67 */
68 public static final Semigroup<Long> longMaximum = Math::max;
69
70 /**
71 * A semigroup that yields the minimum of longs.
72 */
73 public static final Semigroup<Long> longMinimum = Math::min;
74
75 private Semigroups() {}
76
77 /**
78 * Return the first value, ignore the second
79 *
80 * @param <A> result type
81 * @return a {@link io.atlassian.fugue.Semigroup} that ignores the second
82 * input
83 */
84 public static <A> Semigroup<A> first() {
85 return (x, y) -> x;
86 }
87
88 /**
89 * Return the last value, ignore the first
90 *
91 * @param <A> result type
92 * @return a {@link io.atlassian.fugue.Semigroup} that ignores the first input
93 */
94 public static <A> Semigroup<A> last() {
95 return (x, y) -> y;
96 }
97
98 /**
99 * A semigroup for functions.
100 *
101 * @param sb The semigroup for the codomain.
102 * @return A semigroup for functions.
103 * @param <A> input type
104 * @param <B> composable output type
105 */
106 public static <A, B> Semigroup<Function<A, B>> function(final Semigroup<B> sb) {
107 return (a1, a2) -> a -> sb.append(a1.apply(a), a2.apply(a));
108 }
109
110 /**
111 * A semigroup that yields the maximum of by a comparator.
112 *
113 * @param comparator the comparator used to define the max of two value.
114 * @return A max semigroup.
115 * @param <A> result type
116 */
117 public static <A> Semigroup<A> max(final Comparator<A> comparator) {
118 return (a1, a2) -> comparator.compare(a1, a2) < 0 ? a2 : a1;
119 }
120
121 /**
122 * A semigroup that yields the minimum of by a comparator.
123 *
124 * @param comparator the comparator used to define the min of two value.
125 * @return A min semigroup.
126 * @param <A> result type
127 */
128 public static <A> Semigroup<A> min(final Comparator<A> comparator) {
129 return (a1, a2) -> comparator.compare(a1, a2) > 0 ? a2 : a1;
130 }
131
132 /**
133 * A semigroup that yields the maximum of comparable values.
134 *
135 * @return A max semigroup.
136 * @param <A> result type
137 */
138 public static <A extends Comparable<A>> Semigroup<A> max() {
139 return (a1, a2) -> a1.compareTo(a2) < 0 ? a2 : a1;
140 }
141
142 /**
143 * A semigroup that yields the minimum of comparable values.
144 *
145 * @return A min semigroup.
146 * @param <A> result type
147 */
148 public static <A extends Comparable<A>> Semigroup<A> min() {
149 return (a1, a2) -> a1.compareTo(a2) > 0 ? a2 : a1;
150 }
151
152 /**
153 * Sums up values inside either, if both are left or right. Returns first left
154 * otherwise.
155 * <ul>
156 * <li>right(v1) + right(v2) → right(v1 + v2)</li>
157 * <li>right(v1) + -left(v2) → left(v2)</li>
158 * <li>left(v1) + right(v2) → left(v1)</li>
159 * <li>left(v1) + left(v2) → left(v1 + v2)</li>
160 * </ul>
161 *
162 * @param <L> left type
163 * @param <R> right type
164 * @param lS Semigroup for left values
165 * @param rS Semigroup for right values
166 * @return A semigroup that Sums up values inside either.
167 */
168 public static <L, R> Semigroup<Either<L, R>> either(final Semigroup<L> lS, final Semigroup<R> rS) {
169 return (e1, e2) -> e1.<Either<L, R>> fold(l1 -> e2.<Either<L, R>> fold(l2 -> left(lS.append(l1, l2)), r2 -> e1),
170 r1 -> e2.<Either<L, R>> fold(l2 -> e2, r2 -> right(rS.append(r1, r2))));
171 }
172
173 }