Skip to content

Commit abb3263

Browse files
authored
Merge pull request #368 from jbgi/backports/4.x
Backports/4.x
2 parents fb4b5bc + c3ea5d3 commit abb3263

File tree

9 files changed

+73
-36
lines changed

9 files changed

+73
-36
lines changed

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

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import static fj.data.List.nil;
1818
import static fj.data.Natural.natural;
1919
import static fj.data.Option.none;
20+
import static fj.data.Option.some;
2021
import static fj.data.Stream.iterableStream;
2122

2223
import java.math.BigInteger;
@@ -867,6 +868,36 @@ public List<A> sum(F0<Stream<List<A>>> as) {
867868
});
868869
}
869870

871+
/**
872+
* Lift a {@code Semigroup<A>} for A to a {@code Monoid<Option<A>>}, using Option.none() as zero.
873+
*
874+
* @return A monoid for option.
875+
*/
876+
public static <A> Monoid<Option<A>> optionMonoid(Semigroup<A> aSemigroup) {
877+
return monoidDef(new Monoid.Definition<Option<A>>() {
878+
@Override
879+
public Option<A> empty() {
880+
return none();
881+
}
882+
883+
@Override
884+
public Option<A> append(Option<A> a1, Option<A> a2) {
885+
return a1.liftM2(a2, aSemigroup::sum).orElse(a1).orElse(a2);
886+
}
887+
888+
@Override
889+
public Option<A> multiply(int n, Option<A> oa) {
890+
return n > 0 ? oa.map(a -> aSemigroup.multiply1p(n - 1, a)) : none();
891+
}
892+
893+
@Override
894+
public Option<A> sum(F0<Stream<Option<A>>> oas) {
895+
Stream<A> as = oas.f().bind(Option::toStream);
896+
return as.uncons(none(), h -> tail -> some(aSemigroup.sumStream(h, tail::_1)));
897+
}
898+
});
899+
}
900+
870901
/**
871902
* A monoid for options.
872903
* @deprecated since 4.7. Use {@link #firstOptionMonoid()}.

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

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -172,29 +172,7 @@ public Semigroup<A> dual() {
172172
* Lifts the semigroup to obtain a trivial monoid.
173173
*/
174174
public Monoid<Option<A>> lift() {
175-
Definition<A> def = this.def;
176-
return monoidDef(new Monoid.Definition<Option<A>>() {
177-
@Override
178-
public Option<A> empty() {
179-
return none();
180-
}
181-
182-
@Override
183-
public Option<A> append(Option<A> a1, Option<A> a2) {
184-
return a1.liftM2(a1, def::append).orElse(a1).orElse(a2);
185-
}
186-
187-
@Override
188-
public Option<A> multiply(int n, Option<A> oa) {
189-
return n > 0 ? oa.map(a -> def.multiply1p(n - 1, a)) : none();
190-
}
191-
192-
@Override
193-
public Option<A> sum(F0<Stream<Option<A>>> oas) {
194-
Stream<A> as = oas.f().bind(Option::toStream);
195-
return as.uncons(none(), h -> tail -> some(def.sum(h, tail::_1)));
196-
}
197-
});
175+
return Monoid.optionMonoid(this);
198176
}
199177

200178
/**

core/src/main/java/fj/control/Trampoline.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public <R> R fold(final F<Normal<A>, R> n,
4646
// The monadic bind constructs a new Codense whose subcomputation is still `sub`, and Kleisli-composes the
4747
// continuations.
4848
public <B> Trampoline<B> bind(final F<A, Trampoline<B>> f) {
49-
return codense(sub, o -> suspend(P.lazy(() -> cont.f(o).bind(f))));
49+
return codense(sub, o -> suspend(() -> cont.f(o).bind(f)));
5050
}
5151

5252
// The resumption of a Codense is the resumption of its subcomputation. If that computation is done, its result
@@ -126,6 +126,16 @@ public static <A> Trampoline<A> pure(final A a) {
126126
return new Pure<>(a);
127127
}
128128

129+
/**
130+
* Suspends the given computation in a thunk.
131+
*
132+
* @param a A trampoline suspended in a thunk.
133+
* @return A trampoline whose next step runs the given thunk.
134+
*/
135+
public static <A> Trampoline<A> suspend(final F0<Trampoline<A>> a) {
136+
return new Suspend<>(P.lazy(a));
137+
}
138+
129139
/**
130140
* Suspends the given computation in a thunk.
131141
*
@@ -136,6 +146,7 @@ public static <A> Trampoline<A> suspend(final P1<Trampoline<A>> a) {
136146
return new Suspend<>(a);
137147
}
138148

149+
139150
/**
140151
* @return The first-class version of `suspend`.
141152
*/
@@ -255,15 +266,15 @@ public final <B, C> Trampoline<C> zipWith(final Trampoline<B> b, final F2<A, B,
255266
final Either<P1<Trampoline<B>>, B> eb = b.resume();
256267
for (final P1<Trampoline<A>> x : ea.left()) {
257268
for (final P1<Trampoline<B>> y : eb.left()) {
258-
return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(P.lazy(() -> ta.zipWith(tb, f))))));
269+
return suspend(x.bind(y, F2Functions.curry((ta, tb) -> suspend(() -> ta.zipWith(tb, f)))));
259270
}
260271
for (final B y : eb.right()) {
261272
return suspend(x.map(ta -> ta.map(F2Functions.f(F2Functions.flip(f), y))));
262273
}
263274
}
264275
for (final A x : ea.right()) {
265276
for (final B y : eb.right()) {
266-
return suspend(P.lazy(() -> pure(f.f(x, y))));
277+
return suspend(() -> pure(f.f(x, y)));
267278
}
268279
for (final P1<Trampoline<B>> y : eb.left()) {
269280
return suspend(y.map(liftM2(F2Functions.curry(f)).f(pure(x))));

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,6 @@ public DList<A> append(DList<A> other) {
126126
}
127127

128128
private static <A,B,C> F<A,Trampoline<C>> kleisliTrampCompose(F<B,Trampoline<C>> bc, F<A,Trampoline<B>> ab) {
129-
return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(P.lazy(() -> bc.f(b))));
129+
return (A a) -> ab.f(a).bind((B b) -> Trampoline.suspend(() -> bc.f(b)));
130130
}
131131
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ private static final class PureTrampolineEval<A> extends TrampolineEval<A> {
204204

205205
@Override
206206
protected final Trampoline<A> trampoline() {
207-
return Trampoline.suspend(P.lazy(() -> Trampoline.pure(start.value())));
207+
return Trampoline.suspend(() -> Trampoline.pure(start.value()));
208208
}
209209
}
210210

@@ -219,7 +219,7 @@ private static final class BindTrampolineEval<A, B> extends TrampolineEval<B> {
219219

220220
@Override
221221
protected final Trampoline<B> trampoline() {
222-
return Trampoline.suspend(P.lazy(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline())));
222+
return Trampoline.suspend(() -> next.trampoline().bind(v -> f.f(v).asTrampoline().trampoline()));
223223
}
224224
}
225225

@@ -232,7 +232,7 @@ private static final class DeferEval<A> extends TrampolineEval<A> {
232232

233233
@Override
234234
protected final Trampoline<A> trampoline() {
235-
return Trampoline.suspend(P.lazy(() -> memo._1().asTrampoline().trampoline()));
235+
return Trampoline.suspend(() -> memo._1().asTrampoline().trampoline());
236236
}
237237
}
238238
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -736,7 +736,7 @@ public final <B> B foldRight(final F2<A, B, B> f, final B b) {
736736
* @return A Trampoline containing the final result after the right-fold reduction.
737737
*/
738738
public final <B> Trampoline<B> foldRightC(final F2<A, B, B> f, final B b) {
739-
return Trampoline.suspend(P.lazy(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head()))));
739+
return Trampoline.suspend(() -> isEmpty() ? Trampoline.pure(b) : tail().foldRightC(f, b).map(F2Functions.f(f, head())));
740740
}
741741

742742
/**

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import fj.Unit;
66
import fj.control.Trampoline;
77

8-
import static fj.P.lazy;
98
import static fj.P.p;
109
import static fj.control.Trampoline.suspend;
1110
import static fj.data.List.cons;
@@ -75,7 +74,7 @@ public static <S, A, B> State<S, List<B>> traverse(List<A> list, F<A, State<S, B
7574
}
7675

7776
private static <S, A> State<S, A> suspended(F<S, Trampoline<P2<S, A>>> runF) {
78-
return new State<>(s -> suspend(lazy(() -> runF.f(s))));
77+
return new State<>(s -> suspend(() -> runF.f(s)));
7978
}
8079

8180
private final F<S, Trampoline<P2<S, A>>> runF;

core/src/test/java/fj/MonoidTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package fj;
2+
3+
import fj.data.Option;
4+
import fj.data.Stream;
5+
import org.junit.Test;
6+
7+
import static fj.data.Option.some;
8+
import static org.hamcrest.core.Is.is;
9+
import static org.junit.Assert.assertThat;
10+
11+
public class MonoidTest {
12+
13+
@Test
14+
public void lifted_sum_of_two_numbers() {
15+
Monoid<Option<Integer>> optionMonoid = Semigroup.intAdditionSemigroup.lift();
16+
assertThat(optionMonoid.sum(some(3), some(5)), is(some(8)));
17+
assertThat(optionMonoid.sumLeft(Stream.arrayStream(some(3), some(5))), is(some(8)));
18+
}
19+
}

quickcheck/src/main/java/fj/test/Gen.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
import static fj.Function.flip;
1717
import static fj.Monoid.intAdditionMonoid;
1818
import static fj.Ord.intOrd;
19-
import static fj.P.lazy;
2019
import static fj.P2.__1;
2120
import static fj.control.Trampoline.pure;
2221
import static fj.control.Trampoline.suspend;
@@ -551,15 +550,15 @@ final class Tramp {
551550

552551
// Picks elements in constant stack space
553552
private Trampoline<List<A>> tramp(List<A> remainAs, int remainN, int remainALength) {
554-
return suspend(lazy(() ->
553+
return suspend(() ->
555554
(remainN == 0) ?
556555
// We have picked N elements; stop
557556
pure(nil()) :
558557
// For M remaining elements of which N will be picked, pick remainAs.head() with probability N/M
559558
(r.choose(0, remainALength - 1) < remainN) ?
560559
tramp(remainAs.tail(), remainN - 1, remainALength - 1)
561560
.map(pickedTail -> cons(remainAs.head(), pickedTail)) :
562-
tramp(remainAs.tail(), remainN, remainALength - 1)));
561+
tramp(remainAs.tail(), remainN, remainALength - 1));
563562
}
564563

565564
}

0 commit comments

Comments
 (0)