Skip to content

Commit 21dfe75

Browse files
committed
MonadRec instance for SingletonHList and These
1 parent 82c40a4 commit 21dfe75

File tree

4 files changed

+54
-18
lines changed

4 files changed

+54
-18
lines changed

src/main/java/com/jnape/palatable/lambda/adt/These.java

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@
44
import com.jnape.palatable.lambda.adt.coproduct.CoProduct3;
55
import com.jnape.palatable.lambda.adt.hlist.Tuple2;
66
import com.jnape.palatable.lambda.functions.Fn1;
7+
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult;
8+
import com.jnape.palatable.lambda.functions.recursion.Trampoline;
79
import com.jnape.palatable.lambda.functions.specialized.Pure;
810
import com.jnape.palatable.lambda.functor.Applicative;
911
import com.jnape.palatable.lambda.functor.Bifunctor;
1012
import com.jnape.palatable.lambda.functor.builtin.Lazy;
1113
import com.jnape.palatable.lambda.monad.Monad;
14+
import com.jnape.palatable.lambda.monad.MonadRec;
1215
import com.jnape.palatable.lambda.traversable.Traversable;
1316

1417
import java.util.Objects;
1518

1619
import static com.jnape.palatable.lambda.adt.hlist.HList.tuple;
1720
import static com.jnape.palatable.lambda.functions.builtin.fn1.Constantly.constantly;
1821
import static com.jnape.palatable.lambda.functions.builtin.fn2.Into.into;
22+
import static com.jnape.palatable.lambda.functions.builtin.fn2.Sequence.sequence;
1923
import static com.jnape.palatable.lambda.functor.builtin.Lazy.lazy;
2024

2125
/**
@@ -28,7 +32,7 @@
2832
*/
2933
public abstract class These<A, B> implements
3034
CoProduct3<A, B, Tuple2<A, B>, These<A, B>>,
31-
Monad<B, These<A, ?>>,
35+
MonadRec<B, These<A, ?>>,
3236
Bifunctor<A, B, These<?, ?>>,
3337
Traversable<B, These<A, ?>> {
3438

@@ -58,6 +62,17 @@ public final <C> These<A, C> flatMap(Fn1<? super B, ? extends Monad<C, These<A,
5862
into((__, c) -> both(a, c)))));
5963
}
6064

65+
/**
66+
* {@inheritDoc}
67+
*/
68+
@Override
69+
public <C> These<A, C> trampolineM(
70+
Fn1<? super B, ? extends MonadRec<RecursiveResult<B, C>, These<A, ?>>> fn) {
71+
return flatMap(Trampoline.<B, These<A, C>>trampoline(
72+
b -> sequence(fn.apply(b).<These<A, RecursiveResult<B, C>>>coerce(),
73+
RecursiveResult::terminate)));
74+
}
75+
6176
/**
6277
* {@inheritDoc}
6378
*/
@@ -66,6 +81,9 @@ public final <C> These<A, C> pure(C c) {
6681
return match(a -> both(a, c), b -> b(c), into((a, b) -> both(a, c)));
6782
}
6883

84+
/**
85+
* {@inheritDoc}
86+
*/
6987
@Override
7088
@SuppressWarnings("unchecked")
7189
public <C, App extends Applicative<?, App>, TravB extends Traversable<C, These<A, ?>>,
@@ -80,57 +98,55 @@ AppTrav traverse(Fn1<? super B, ? extends Applicative<C, App>> fn, Fn1<? super T
8098
* {@inheritDoc}
8199
*/
82100
@Override
83-
@SuppressWarnings("unchecked")
84101
public final <Z> These<Z, B> biMapL(Fn1<? super A, ? extends Z> fn) {
85-
return (These<Z, B>) Bifunctor.super.biMapL(fn);
102+
return (These<Z, B>) Bifunctor.super.<Z>biMapL(fn);
86103
}
87104

88105
/**
89106
* {@inheritDoc}
90107
*/
91108
@Override
92-
@SuppressWarnings("unchecked")
93109
public final <C> These<A, C> biMapR(Fn1<? super B, ? extends C> fn) {
94-
return (These<A, C>) Bifunctor.super.biMapR(fn);
110+
return (These<A, C>) Bifunctor.super.<C>biMapR(fn);
95111
}
96112

97113
/**
98114
* {@inheritDoc}
99115
*/
100116
@Override
101117
public final <C> These<A, C> fmap(Fn1<? super B, ? extends C> fn) {
102-
return Monad.super.<C>fmap(fn).coerce();
118+
return MonadRec.super.<C>fmap(fn).coerce();
103119
}
104120

105121
/**
106122
* {@inheritDoc}
107123
*/
108124
@Override
109125
public final <C> These<A, C> zip(Applicative<Fn1<? super B, ? extends C>, These<A, ?>> appFn) {
110-
return Monad.super.zip(appFn).coerce();
126+
return MonadRec.super.zip(appFn).coerce();
111127
}
112128

113129
@Override
114130
public <C> Lazy<These<A, C>> lazyZip(
115131
Lazy<? extends Applicative<Fn1<? super B, ? extends C>, These<A, ?>>> lazyAppFn) {
116132
return projectA().<Lazy<These<A, C>>>fmap(a -> lazy(a(a)))
117-
.orElseGet(() -> Monad.super.lazyZip(lazyAppFn).fmap(Monad<C, These<A, ?>>::coerce));
133+
.orElseGet(() -> MonadRec.super.lazyZip(lazyAppFn).fmap(Monad<C, These<A, ?>>::coerce));
118134
}
119135

120136
/**
121137
* {@inheritDoc}
122138
*/
123139
@Override
124140
public final <C> These<A, C> discardL(Applicative<C, These<A, ?>> appB) {
125-
return Monad.super.discardL(appB).coerce();
141+
return MonadRec.super.discardL(appB).coerce();
126142
}
127143

128144
/**
129145
* {@inheritDoc}
130146
*/
131147
@Override
132148
public final <C> These<A, B> discardR(Applicative<C, These<A, ?>> appB) {
133-
return Monad.super.discardR(appB).coerce();
149+
return MonadRec.super.discardR(appB).coerce();
134150
}
135151

136152
/**

src/main/java/com/jnape/palatable/lambda/adt/hlist/SingletonHList.java

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@
33
import com.jnape.palatable.lambda.adt.hlist.HList.HCons;
44
import com.jnape.palatable.lambda.adt.hlist.HList.HNil;
55
import com.jnape.palatable.lambda.functions.Fn1;
6+
import com.jnape.palatable.lambda.functions.recursion.RecursiveResult;
67
import com.jnape.palatable.lambda.functions.specialized.Pure;
78
import com.jnape.palatable.lambda.functor.Applicative;
89
import com.jnape.palatable.lambda.functor.builtin.Lazy;
910
import com.jnape.palatable.lambda.monad.Monad;
11+
import com.jnape.palatable.lambda.monad.MonadRec;
1012
import com.jnape.palatable.lambda.traversable.Traversable;
1113

14+
import static com.jnape.palatable.lambda.functions.recursion.Trampoline.trampoline;
15+
1216
/**
1317
* A singleton HList. Supports random access.
1418
*
@@ -20,7 +24,7 @@
2024
* @see Tuple5
2125
*/
2226
public class SingletonHList<_1> extends HCons<_1, HNil> implements
23-
Monad<_1, SingletonHList<?>>,
27+
MonadRec<_1, SingletonHList<?>>,
2428
Traversable<_1, SingletonHList<?>> {
2529

2630
SingletonHList(_1 _1) {
@@ -40,7 +44,7 @@ public <_0> Tuple2<_0, _1> cons(_0 _0) {
4044
*/
4145
@Override
4246
public <_1Prime> SingletonHList<_1Prime> fmap(Fn1<? super _1, ? extends _1Prime> fn) {
43-
return Monad.super.<_1Prime>fmap(fn).coerce();
47+
return MonadRec.super.<_1Prime>fmap(fn).coerce();
4448
}
4549

4650
/**
@@ -57,7 +61,7 @@ public <_1Prime> SingletonHList<_1Prime> pure(_1Prime _1Prime) {
5761
@Override
5862
public <_1Prime> SingletonHList<_1Prime> zip(
5963
Applicative<Fn1<? super _1, ? extends _1Prime>, SingletonHList<?>> appFn) {
60-
return Monad.super.zip(appFn).coerce();
64+
return MonadRec.super.zip(appFn).coerce();
6165
}
6266

6367
/**
@@ -66,23 +70,23 @@ public <_1Prime> SingletonHList<_1Prime> zip(
6670
@Override
6771
public <_1Prime> Lazy<SingletonHList<_1Prime>> lazyZip(
6872
Lazy<? extends Applicative<Fn1<? super _1, ? extends _1Prime>, SingletonHList<?>>> lazyAppFn) {
69-
return Monad.super.lazyZip(lazyAppFn).fmap(Monad<_1Prime, SingletonHList<?>>::coerce);
73+
return MonadRec.super.lazyZip(lazyAppFn).fmap(Monad<_1Prime, SingletonHList<?>>::coerce);
7074
}
7175

7276
/**
7377
* {@inheritDoc}
7478
*/
7579
@Override
7680
public <_1Prime> SingletonHList<_1Prime> discardL(Applicative<_1Prime, SingletonHList<?>> appB) {
77-
return Monad.super.discardL(appB).coerce();
81+
return MonadRec.super.discardL(appB).coerce();
7882
}
7983

8084
/**
8185
* {@inheritDoc}
8286
*/
8387
@Override
8488
public <_1Prime> SingletonHList<_1> discardR(Applicative<_1Prime, SingletonHList<?>> appB) {
85-
return Monad.super.discardR(appB).coerce();
89+
return MonadRec.super.discardR(appB).coerce();
8690
}
8791

8892
/**
@@ -93,6 +97,15 @@ public <_1Prime> SingletonHList<_1Prime> flatMap(Fn1<? super _1, ? extends Monad
9397
return f.apply(head()).coerce();
9498
}
9599

100+
/**
101+
* {@inheritDoc}
102+
*/
103+
@Override
104+
public <_1Prime> SingletonHList<_1Prime> trampolineM(
105+
Fn1<? super _1, ? extends MonadRec<RecursiveResult<_1, _1Prime>, SingletonHList<?>>> fn) {
106+
return fmap(trampoline(head -> fn.apply(head).<SingletonHList<RecursiveResult<_1, _1Prime>>>coerce().head()));
107+
}
108+
96109
/**
97110
* {@inheritDoc}
98111
*/

src/test/java/com/jnape/palatable/lambda/adt/TheseTest.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import testsupport.traits.BifunctorLaws;
1010
import testsupport.traits.FunctorLaws;
1111
import testsupport.traits.MonadLaws;
12+
import testsupport.traits.MonadRecLaws;
1213
import testsupport.traits.TraversableLaws;
1314

1415
import static com.jnape.palatable.lambda.adt.These.a;
@@ -21,7 +22,12 @@
2122
@RunWith(Traits.class)
2223
public class TheseTest {
2324

24-
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, TraversableLaws.class, BifunctorLaws.class})
25+
@TestTraits({FunctorLaws.class,
26+
ApplicativeLaws.class,
27+
MonadLaws.class,
28+
MonadRecLaws.class,
29+
TraversableLaws.class,
30+
BifunctorLaws.class})
2531
public Subjects<These<String, Integer>> testSubject() {
2632
return subjects(a("foo"), b(1), both("foo", 1));
2733
}

src/test/java/com/jnape/palatable/lambda/adt/hlist/SingletonHListTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import testsupport.traits.ApplicativeLaws;
99
import testsupport.traits.FunctorLaws;
1010
import testsupport.traits.MonadLaws;
11+
import testsupport.traits.MonadRecLaws;
1112
import testsupport.traits.TraversableLaws;
1213

1314
import static com.jnape.palatable.lambda.adt.hlist.HList.nil;
@@ -25,7 +26,7 @@ public void setUp() {
2526
singletonHList = new SingletonHList<>(1);
2627
}
2728

28-
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, TraversableLaws.class})
29+
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, TraversableLaws.class, MonadRecLaws.class})
2930
public SingletonHList<?> testSubject() {
3031
return singletonHList("one");
3132
}

0 commit comments

Comments
 (0)