Skip to content

Commit 83ed2c6

Browse files
gshakhnjnape
authored andcommitted
MonadRec implementation for Choice2
1 parent 73dc6b4 commit 83ed2c6

File tree

2 files changed

+28
-14
lines changed

2 files changed

+28
-14
lines changed

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

Lines changed: 19 additions & 6 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.Tuple2;
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.Into.into;
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
/**
@@ -30,7 +34,7 @@
3034
*/
3135
public abstract class Choice2<A, B> implements
3236
CoProduct2<A, B, Choice2<A, B>>,
33-
Monad<B, Choice2<A, ?>>,
37+
MonadRec<B, Choice2<A, ?>>,
3438
Bifunctor<A, B, Choice2<?, ?>>,
3539
Traversable<B, Choice2<A, ?>> {
3640

@@ -68,7 +72,7 @@ public Choice2<B, A> invert() {
6872
*/
6973
@Override
7074
public final <C> Choice2<A, C> fmap(Fn1<? super B, ? extends C> fn) {
71-
return Monad.super.<C>fmap(fn).coerce();
75+
return MonadRec.super.<C>fmap(fn).coerce();
7276
}
7377

7478
/**
@@ -109,14 +113,14 @@ public <C> Choice2<A, C> pure(C c) {
109113
*/
110114
@Override
111115
public <C> Choice2<A, C> zip(Applicative<Fn1<? super B, ? extends C>, Choice2<A, ?>> appFn) {
112-
return Monad.super.zip(appFn).coerce();
116+
return MonadRec.super.zip(appFn).coerce();
113117
}
114118

115119
/**
116120
* {@inheritDoc}
117121
*/
118122
@Override
119-
public <C> Lazy<? extends Monad<C, Choice2<A, ?>>> lazyZip(
123+
public <C> Lazy<Choice2<A, C>> lazyZip(
120124
Lazy<? extends Applicative<Fn1<? super B, ? extends C>, Choice2<A, ?>>> lazyAppFn) {
121125
return match(a -> lazy(a(a)),
122126
b -> lazyAppFn.fmap(choiceF -> choiceF.<C>fmap(f -> f.apply(b)).coerce()));
@@ -127,15 +131,15 @@ public <C> Choice2<A, C> zip(Applicative<Fn1<? super B, ? extends C>, Choice2<A,
127131
*/
128132
@Override
129133
public <C> Choice2<A, C> discardL(Applicative<C, Choice2<A, ?>> appB) {
130-
return Monad.super.discardL(appB).coerce();
134+
return MonadRec.super.discardL(appB).coerce();
131135
}
132136

133137
/**
134138
* {@inheritDoc}
135139
*/
136140
@Override
137141
public <C> Choice2<A, B> discardR(Applicative<C, Choice2<A, ?>> appB) {
138-
return Monad.super.discardR(appB).coerce();
142+
return MonadRec.super.discardR(appB).coerce();
139143
}
140144

141145
/**
@@ -146,6 +150,15 @@ public final <C> Choice2<A, C> flatMap(Fn1<? super B, ? extends Monad<C, Choice2
146150
return match(Choice2::a, b -> f.apply(b).coerce());
147151
}
148152

153+
@Override
154+
public <C> Choice2<A, C> trampolineM(Fn1<? super B, ? extends MonadRec<RecursiveResult<B, C>, Choice2<A, ?>>> fn) {
155+
return match(Choice2::a,
156+
trampoline(b -> fn.apply(b)
157+
.<Choice2<A, RecursiveResult<B, C>>>coerce()
158+
.match(a -> terminate(a(a)),
159+
bOrC -> bOrC.fmap(Choice2::b))));
160+
}
161+
149162
/**
150163
* {@inheritDoc}
151164
*/

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@
66
import org.junit.Before;
77
import org.junit.Test;
88
import org.junit.runner.RunWith;
9-
import testsupport.traits.ApplicativeLaws;
10-
import testsupport.traits.BifunctorLaws;
11-
import testsupport.traits.FunctorLaws;
12-
import testsupport.traits.MonadLaws;
13-
import testsupport.traits.TraversableLaws;
9+
import testsupport.traits.*;
1410

1511
import static com.jnape.palatable.lambda.adt.choice.Choice2.a;
1612
import static com.jnape.palatable.lambda.adt.choice.Choice2.b;
@@ -30,15 +26,20 @@ public void setUp() {
3026
b = b(true);
3127
}
3228

33-
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, BifunctorLaws.class, TraversableLaws.class})
29+
@TestTraits({FunctorLaws.class,
30+
ApplicativeLaws.class,
31+
MonadLaws.class,
32+
BifunctorLaws.class,
33+
TraversableLaws.class,
34+
MonadRecLaws.class})
3435
public Subjects<Choice2<String, Integer>> testSubjects() {
3536
return subjects(a("foo"), b(1));
3637
}
3738

3839
@Test
3940
public void divergeStaysInChoice() {
40-
assertEquals(Choice3.a(1), a.diverge());
41-
assertEquals(Choice3.b(true), b.diverge());
41+
assertEquals(Choice3.<Integer, Boolean, Object>a(1), a.diverge());
42+
assertEquals(Choice3.<Integer, Boolean, Object>b(true), b.diverge());
4243
}
4344

4445
@Test

0 commit comments

Comments
 (0)