Skip to content

Commit 73dc6b4

Browse files
sdurijnape
authored andcommitted
MonadRec implementation for Choice4
1 parent 6e95041 commit 73dc6b4

File tree

2 files changed

+37
-14
lines changed

2 files changed

+37
-14
lines changed

src/main/java/com/jnape/palatable/lambda/adt/choice/Choice4.java

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,21 @@
66
import com.jnape.palatable.lambda.adt.hlist.HList;
77
import com.jnape.palatable.lambda.adt.hlist.Tuple4;
88
import com.jnape.palatable.lambda.functions.Fn1;
9+
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult;
910
import com.jnape.palatable.lambda.functions.specialized.Pure;
1011
import com.jnape.palatable.lambda.functor.Applicative;
1112
import com.jnape.palatable.lambda.functor.Bifunctor;
1213
import com.jnape.palatable.lambda.functor.Functor;
1314
import com.jnape.palatable.lambda.functor.builtin.Lazy;
1415
import com.jnape.palatable.lambda.monad.Monad;
16+
import com.jnape.palatable.lambda.monad.MonadRec;
1517
import com.jnape.palatable.lambda.traversable.Traversable;
1618

1719
import java.util.Objects;
1820

1921
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into4.into4;
22+
import static com.jnape.palatable.lambda.functions.recursion.RecursiveResult.terminate;
23+
import static com.jnape.palatable.lambda.functions.recursion.Trampoline.trampoline;
2024
import static com.jnape.palatable.lambda.functor.builtin.Lazy.lazy;
2125

2226
/**
@@ -31,7 +35,7 @@
3135
*/
3236
public abstract class Choice4<A, B, C, D> implements
3337
CoProduct4<A, B, C, D, Choice4<A, B, C, D>>,
34-
Monad<D, Choice4<A, B, C, ?>>,
38+
MonadRec<D, Choice4<A, B, C, ?>>,
3539
Bifunctor<C, D, Choice4<A, B, ?, ?>>,
3640
Traversable<D, Choice4<A, B, C, ?>> {
3741

@@ -70,7 +74,7 @@ public Choice3<A, B, C> converge(Fn1<? super D, ? extends CoProduct3<A, B, C, ?>
7074
*/
7175
@Override
7276
public final <E> Choice4<A, B, C, E> fmap(Fn1<? super D, ? extends E> fn) {
73-
return Monad.super.<E>fmap(fn).coerce();
77+
return MonadRec.super.<E>fmap(fn).coerce();
7478
}
7579

7680
/**
@@ -108,7 +112,7 @@ public <E> Choice4<A, B, C, E> pure(E e) {
108112
*/
109113
@Override
110114
public <E> Choice4<A, B, C, E> zip(Applicative<Fn1<? super D, ? extends E>, Choice4<A, B, C, ?>> appFn) {
111-
return Monad.super.zip(appFn).coerce();
115+
return MonadRec.super.zip(appFn).coerce();
112116
}
113117

114118
/**
@@ -128,15 +132,15 @@ public <E> Lazy<Choice4<A, B, C, E>> lazyZip(
128132
*/
129133
@Override
130134
public <E> Choice4<A, B, C, E> discardL(Applicative<E, Choice4<A, B, C, ?>> appB) {
131-
return Monad.super.discardL(appB).coerce();
135+
return MonadRec.super.discardL(appB).coerce();
132136
}
133137

134138
/**
135139
* {@inheritDoc}
136140
*/
137141
@Override
138142
public <E> Choice4<A, B, C, D> discardR(Applicative<E, Choice4<A, B, C, ?>> appB) {
139-
return Monad.super.discardR(appB).coerce();
143+
return MonadRec.super.discardR(appB).coerce();
140144
}
141145

142146
/**
@@ -161,6 +165,19 @@ AppTrav extends Applicative<TravB, App>> AppTrav traverse(Fn1<? super D, ? exten
161165
d -> fn.apply(d).<Choice4<A, B, C, E>>fmap(Choice4::d).<TravB>fmap(Functor::coerce).coerce());
162166
}
163167

168+
@Override
169+
public <E> Choice4<A, B, C, E> trampolineM(
170+
Fn1<? super D, ? extends MonadRec<RecursiveResult<D, E>, Choice4<A, B, C, ?>>> fn) {
171+
return match(Choice4::a,
172+
Choice4::b,
173+
Choice4::c,
174+
trampoline(d -> fn.apply(d).<Choice4<A, B, C, RecursiveResult<D, E>>>coerce()
175+
.match(a -> terminate(a(a)),
176+
b -> terminate(b(b)),
177+
c -> terminate(c(c)),
178+
dOrE -> dOrE.fmap(Choice4::d))));
179+
}
180+
164181
/**
165182
* Static factory method for wrapping a value of type <code>A</code> in a {@link Choice4}.
166183
*

src/test/java/com/jnape/palatable/lambda/adt/choice/Choice4Test.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import testsupport.traits.BifunctorLaws;
1111
import testsupport.traits.FunctorLaws;
1212
import testsupport.traits.MonadLaws;
13+
import testsupport.traits.MonadRecLaws;
1314
import testsupport.traits.TraversableLaws;
1415

1516
import static com.jnape.palatable.lambda.adt.choice.Choice4.a;
@@ -36,25 +37,30 @@ public void setUp() {
3637
d = d(4D);
3738
}
3839

39-
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, BifunctorLaws.class, TraversableLaws.class})
40+
@TestTraits({FunctorLaws.class,
41+
ApplicativeLaws.class,
42+
MonadLaws.class,
43+
BifunctorLaws.class,
44+
TraversableLaws.class,
45+
MonadRecLaws.class})
4046
public Subjects<Choice4<String, Integer, Boolean, Character>> testSubjects() {
4147
return subjects(a("foo"), b(1), c(true), d('a'));
4248
}
4349

4450
@Test
4551
public void convergeStaysInChoice() {
46-
assertEquals(Choice3.a(1), a.converge(d -> Choice3.b(d.toString())));
47-
assertEquals(Choice3.b("two"), b.converge(d -> Choice3.b(d.toString())));
48-
assertEquals(Choice3.c(true), c.converge(d -> Choice3.b(d.toString())));
49-
assertEquals(Choice3.b("4.0"), d.converge(d -> Choice3.b(d.toString())));
52+
assertEquals(Choice3.<Integer, String, Boolean>a(1), a.converge(d -> Choice3.b(d.toString())));
53+
assertEquals(Choice3.<Integer, String, Boolean>b("two"), b.converge(d -> Choice3.b(d.toString())));
54+
assertEquals(Choice3.<Integer, String, Boolean>c(true), c.converge(d -> Choice3.b(d.toString())));
55+
assertEquals(Choice3.<Integer, String, Boolean>b("4.0"), d.converge(d -> Choice3.b(d.toString())));
5056
}
5157

5258
@Test
5359
public void divergeStaysInChoice() {
54-
assertEquals(Choice5.a(1), a.diverge());
55-
assertEquals(Choice5.b("two"), b.diverge());
56-
assertEquals(Choice5.c(true), c.diverge());
57-
assertEquals(Choice5.d(4D), d.diverge());
60+
assertEquals(Choice5.<Integer, String, Boolean, Double, Object>a(1), a.diverge());
61+
assertEquals(Choice5.<Integer, String, Boolean, Double, Object>b("two"), b.diverge());
62+
assertEquals(Choice5.<Integer, String, Boolean, Double, Object>c(true), c.diverge());
63+
assertEquals(Choice5.<Integer, String, Boolean, Double, Object>d(4D), d.diverge());
5864
}
5965

6066
@Test

0 commit comments

Comments
 (0)