Skip to content

Commit cf1188a

Browse files
committed
Fix regression in lifted semigroup sum. Move lifted definition in Monoid.
1 parent fb4b5bc commit cf1188a

File tree

3 files changed

+51
-23
lines changed

3 files changed

+51
-23
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/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+
}

0 commit comments

Comments
 (0)