Skip to content

Commit 6b3905d

Browse files
committed
Merge pull request #251 from puffnfresh/feature/semigroups
More Semigroup additions
2 parents 3716e73 + 0386eb7 commit 6b3905d

File tree

4 files changed

+71
-11
lines changed

4 files changed

+71
-11
lines changed

core/src/main/java/fj/Monoid.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import fj.data.Set;
1212
import fj.data.Stream;
1313

14+
import static fj.Function.flip;
1415
import static fj.Semigroup.multiply1p;
1516
import static fj.data.Stream.iterableStream;
1617

@@ -191,6 +192,13 @@ public A join(final Iterable<A> as, final A a) {
191192
s.foldLeft1(Function.compose(sum, flip(sum).f(a)));
192193
}
193194

195+
/**
196+
* Swaps the arguments when summing.
197+
*/
198+
public Monoid<A> dual() {
199+
return monoid(flip(sum), zero);
200+
}
201+
194202
/**
195203
* Constructs a monoid from the given sum function and zero value, which must follow the monoidal
196204
* laws.

core/src/main/java/fj/Ord.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import java.util.Comparator;
1616

1717
import static fj.Function.curry;
18+
import static fj.Semigroup.semigroup;
1819

1920
/**
2021
* Tests for ordering between two objects.
@@ -157,7 +158,15 @@ public A min(final A a1, final A a2) {
157158
*/
158159
public final F<A, F<A, A>> min = curry(this::min);
159160

160-
public Ord<A> reverse() { return ord(Function.flip(f)); }
161+
public final Semigroup<A> minSemigroup() {
162+
return semigroup(this::min);
163+
}
164+
165+
public final Semigroup<A> maxSemigroup() {
166+
return semigroup(this::max);
167+
}
168+
169+
public final Ord<A> reverse() { return ord(Function.flip(f)); }
161170

162171
/**
163172
* Returns an order instance that uses the given equality test and ordering function.

core/src/main/java/fj/Semigroup.java

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
import java.math.BigInteger;
1515

1616
import static fj.Function.curry;
17+
import static fj.Function.flip;
1718

1819
/**
1920
* Implementations must satisfy the law of associativity:
@@ -96,6 +97,27 @@ static <A> A multiply1p(F<A, F<A, A>> sum, int n, A a) {
9697
}
9798
}
9899

100+
/**
101+
* Sums the given values with left-fold.
102+
*/
103+
public A sumNel(final NonEmptyList<A> as) {
104+
return as.foldLeft1(sum);
105+
}
106+
107+
/**
108+
* Swaps the arguments when summing.
109+
*/
110+
public Semigroup<A> dual() {
111+
return semigroup(flip(sum));
112+
}
113+
114+
/**
115+
* Lifts the semigroup to obtain a trivial monoid.
116+
*/
117+
public Monoid<Option<A>> lift() {
118+
return Monoid.monoid(a -> b -> Option.liftM2(sum).f(a).f(b).orElse(a).orElse(b), Option.none());
119+
}
120+
99121
/**
100122
* Constructs a semigroup from the given function.
101123
*
@@ -139,12 +161,12 @@ public static <A> Semigroup<A> semigroup(final F2<A, A, A> sum) {
139161
/**
140162
* A semigroup that yields the maximum of integers.
141163
*/
142-
public static final Semigroup<Integer> intMaximumSemigroup = semigroup(Ord.intOrd.max);
164+
public static final Semigroup<Integer> intMaximumSemigroup = Ord.intOrd.maxSemigroup();
143165

144166
/**
145167
* A semigroup that yields the minimum of integers.
146168
*/
147-
public static final Semigroup<Integer> intMinimumSemigroup = semigroup(Ord.intOrd.min);
169+
public static final Semigroup<Integer> intMinimumSemigroup = Ord.intOrd.minSemigroup();
148170

149171
/**
150172
* A semigroup that adds big integers.
@@ -161,12 +183,12 @@ public static <A> Semigroup<A> semigroup(final F2<A, A, A> sum) {
161183
/**
162184
* A semigroup that yields the maximum of big integers.
163185
*/
164-
public static final Semigroup<BigInteger> bigintMaximumSemigroup = semigroup(Ord.bigintOrd.max);
186+
public static final Semigroup<BigInteger> bigintMaximumSemigroup = Ord.bigintOrd.maxSemigroup();
165187

166188
/**
167189
* A semigroup that yields the minimum of big integers.
168190
*/
169-
public static final Semigroup<BigInteger> bigintMinimumSemigroup = semigroup(Ord.bigintOrd.min);
191+
public static final Semigroup<BigInteger> bigintMinimumSemigroup = Ord.bigintOrd.minSemigroup();
170192

171193
/**
172194
* A semigroup that adds big decimals.
@@ -183,12 +205,12 @@ public static <A> Semigroup<A> semigroup(final F2<A, A, A> sum) {
183205
/**
184206
* A semigroup that yields the maximum of big decimals.
185207
*/
186-
public static final Semigroup<BigDecimal> bigDecimalMaximumSemigroup = semigroup(Ord.bigdecimalOrd.max);
208+
public static final Semigroup<BigDecimal> bigDecimalMaximumSemigroup = Ord.bigdecimalOrd.maxSemigroup();
187209

188210
/**
189211
* A semigroup that yields the minimum of big decimals.
190212
*/
191-
public static final Semigroup<BigDecimal> bigDecimalMinimumSemigroup = semigroup(Ord.bigdecimalOrd.min);
213+
public static final Semigroup<BigDecimal> bigDecimalMinimumSemigroup = Ord.bigdecimalOrd.minSemigroup();
192214

193215
/**
194216
* A semigroup that multiplies natural numbers.
@@ -205,12 +227,12 @@ public static <A> Semigroup<A> semigroup(final F2<A, A, A> sum) {
205227
/**
206228
* A semigroup that yields the maximum of natural numbers.
207229
*/
208-
public static final Semigroup<Natural> naturalMaximumSemigroup = semigroup(Ord.naturalOrd.max);
230+
public static final Semigroup<Natural> naturalMaximumSemigroup = Ord.naturalOrd.maxSemigroup();
209231

210232
/**
211233
* A semigroup that yields the minimum of natural numbers.
212234
*/
213-
public static final Semigroup<Natural> naturalMinimumSemigroup = semigroup(Ord.naturalOrd.min);
235+
public static final Semigroup<Natural> naturalMinimumSemigroup = Ord.naturalOrd.minSemigroup();
214236

215237
/**
216238
* A semigroup that adds longs.
@@ -225,12 +247,12 @@ public static <A> Semigroup<A> semigroup(final F2<A, A, A> sum) {
225247
/**
226248
* A semigroup that yields the maximum of longs.
227249
*/
228-
public static final Semigroup<Long> longMaximumSemigroup = semigroup(Ord.longOrd.max);
250+
public static final Semigroup<Long> longMaximumSemigroup = Ord.longOrd.maxSemigroup();
229251

230252
/**
231253
* A semigroup that yields the minimum of longs.
232254
*/
233-
public static final Semigroup<Long> longMinimumSemigroup = semigroup(Ord.longOrd.min);
255+
public static final Semigroup<Long> longMinimumSemigroup = Ord.longOrd.minSemigroup();
234256

235257
/**
236258
* A semigroup that ORs booleans.

core/src/main/java/fj/data/NonEmptyList.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.util.Collection;
77
import java.util.Iterator;
88

9+
import static fj.Function.flip;
910
import static fj.Function.identity;
1011
import static fj.data.Option.some;
1112
import static fj.data.Option.somes;
@@ -87,6 +88,26 @@ public NonEmptyList<A> append(final NonEmptyList<A> as) {
8788
return nel(head, bb);
8889
}
8990

91+
/**
92+
* Performs a right-fold reduction across this list. This function uses O(length) stack space.
93+
*/
94+
public final A foldRight1(final F<A, F<A, A>> f) {
95+
return reverse().foldLeft1(flip(f));
96+
}
97+
98+
/**
99+
* Performs a left-fold reduction across this list. This function runs in constant space.
100+
*/
101+
public final A foldLeft1(final F<A, F<A, A>> f) {
102+
A x = head;
103+
104+
for (List<A> xs = tail; !xs.isEmpty(); xs = xs.tail()) {
105+
x = f.f(x).f(xs.head());
106+
}
107+
108+
return x;
109+
}
110+
90111
/**
91112
* Maps the given function across this list.
92113
*

0 commit comments

Comments
 (0)