Skip to content

Commit 34bcc6d

Browse files
committed
ReaderT retains a Pure m instance
1 parent 1f5b9f0 commit 34bcc6d

File tree

2 files changed

+42
-31
lines changed
  • src
    • main/java/com/jnape/palatable/lambda/monad/transformer/builtin
    • test/java/com/jnape/palatable/lambda/monad/transformer/builtin

2 files changed

+42
-31
lines changed

src/main/java/com/jnape/palatable/lambda/monad/transformer/builtin/ReaderT.java

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,12 @@ public final class ReaderT<R, M extends MonadRec<?, M>, A> implements
3030
Cartesian<R, A, ReaderT<?, M, ?>>,
3131
MonadT<M, A, ReaderT<R, M, ?>, ReaderT<R, ?, ?>> {
3232

33+
private final Pure<M> pureM;
3334
private final Fn1<? super R, ? extends MonadRec<A, M>> f;
3435

35-
private ReaderT(Fn1<? super R, ? extends MonadRec<A, M>> f) {
36-
this.f = f;
36+
private ReaderT(Pure<M> pureM, Fn1<? super R, ? extends MonadRec<A, M>> f) {
37+
this.pureM = pureM;
38+
this.f = f;
3739
}
3840

3941
/**
@@ -50,15 +52,16 @@ public <MA extends MonadRec<A, M>> MA runReaderT(R r) {
5052
/**
5153
* Map the current {@link Monad monadic} embedding to a new one in a potentially different {@link Monad}.
5254
*
53-
* @param fn the function
54-
* @param <MA> the currently embedded {@link Monad}
55-
* @param <N> the new {@link Monad} witness
56-
* @param <B> the new carrier type
55+
* @param fn the function
56+
* @param pureN the new {@link MonadRec monad's} {@link Pure} instance
57+
* @param <MA> the currently embedded {@link Monad}
58+
* @param <N> the new {@link Monad} witness
59+
* @param <B> the new carrier type
5760
* @return the mapped {@link ReaderT}
5861
*/
5962
public <MA extends MonadRec<A, M>, N extends MonadRec<?, N>, B> ReaderT<R, N, B> mapReaderT(
60-
Fn1<? super MA, ? extends MonadRec<B, N>> fn) {
61-
return readerT(r -> fn.apply(runReaderT(r).coerce()));
63+
Fn1<? super MA, ? extends MonadRec<B, N>> fn, Pure<N> pureN) {
64+
return readerT(r -> fn.apply(runReaderT(r).coerce()), pureN);
6265
}
6366

6467
/**
@@ -70,7 +73,7 @@ public <MA extends MonadRec<A, M>, N extends MonadRec<?, N>, B> ReaderT<R, N, B>
7073
* @return the composed {@link ReaderT}
7174
*/
7275
public <B> ReaderT<R, M, B> and(ReaderT<A, M, B> amb) {
73-
return readerT(r -> runReaderT(r).flatMap(amb::runReaderT));
76+
return readerT(r -> runReaderT(r).flatMap(amb::runReaderT), pureM);
7477
}
7578

7679
/**
@@ -94,7 +97,7 @@ public <B, N extends MonadRec<?, N>> ReaderT<R, N, B> lift(MonadRec<B, N> mb) {
9497
*/
9598
@Override
9699
public <B> ReaderT<R, M, B> flatMap(Fn1<? super A, ? extends Monad<B, ReaderT<R, M, ?>>> f) {
97-
return readerT(r -> runReaderT(r).flatMap(a -> f.apply(a).<ReaderT<R, M, B>>coerce().runReaderT(r)));
100+
return readerT(r -> runReaderT(r).flatMap(a -> f.apply(a).<ReaderT<R, M, B>>coerce().runReaderT(r)), pureM);
98101
}
99102

100103
/**
@@ -104,15 +107,16 @@ public <B> ReaderT<R, M, B> flatMap(Fn1<? super A, ? extends Monad<B, ReaderT<R,
104107
public <B> ReaderT<R, M, B> trampolineM(
105108
Fn1<? super A, ? extends MonadRec<RecursiveResult<A, B>, ReaderT<R, M, ?>>> fn) {
106109
return readerT(r -> runReaderT(r).trampolineM(a -> fn.apply(a).<ReaderT<R, M, RecursiveResult<A, B>>>coerce()
107-
.runReaderT(r)));
110+
.runReaderT(r)), pureM);
108111
}
109112

110113
/**
111114
* {@inheritDoc}
112115
*/
113116
@Override
114117
public <B> ReaderT<R, M, B> pure(B b) {
115-
return readerT(r -> runReaderT(r).pure(b));
118+
MonadRec<B, M> mb = pureM.apply(b);
119+
return readerT(r -> mb, pureM);
116120
}
117121

118122
/**
@@ -128,7 +132,7 @@ public <B> ReaderT<R, M, B> fmap(Fn1<? super A, ? extends B> fn) {
128132
*/
129133
@Override
130134
public <B> ReaderT<R, M, B> zip(Applicative<Fn1<? super A, ? extends B>, ReaderT<R, M, ?>> appFn) {
131-
return readerT(r -> f.apply(r).zip(appFn.<ReaderT<R, M, Fn1<? super A, ? extends B>>>coerce().runReaderT(r)));
135+
return readerT(r -> f.apply(r).zip(appFn.<ReaderT<R, M, Fn1<? super A, ? extends B>>>coerce().runReaderT(r)), pureM);
132136
}
133137

134138
/**
@@ -161,7 +165,7 @@ public <B> ReaderT<R, M, A> discardR(Applicative<B, ReaderT<R, M, ?>> appB) {
161165
*/
162166
@Override
163167
public <Q, B> ReaderT<Q, M, B> diMap(Fn1<? super Q, ? extends R> lFn, Fn1<? super A, ? extends B> rFn) {
164-
return readerT(q -> runReaderT(lFn.apply(q)).fmap(rFn));
168+
return readerT(q -> runReaderT(lFn.apply(q)).fmap(rFn), pureM);
165169
}
166170

167171
/**
@@ -193,7 +197,7 @@ public <Q> ReaderT<Q, M, A> contraMap(Fn1<? super Q, ? extends R> fn) {
193197
*/
194198
@Override
195199
public <C> ReaderT<Tuple2<C, R>, M, Tuple2<C, A>> cartesian() {
196-
return readerT(into((c, r) -> runReaderT(r).fmap(tupler(c))));
200+
return readerT(into((c, r) -> runReaderT(r).fmap(tupler(c))), pureM);
197201
}
198202

199203
/**
@@ -207,15 +211,16 @@ public ReaderT<R, M, Tuple2<R, A>> carry() {
207211
/**
208212
* Lift a {@link Fn1 function} (<code>R -&gt; {@link Monad}&lt;A, M&gt;</code>) into a {@link ReaderT} instance.
209213
*
210-
* @param fn the function
211-
* @param <R> the input type
212-
* @param <M> the returned {@link Monad}
213-
* @param <A> the embedded output type
214+
* @param fn the function
215+
* @param pureM the {@link MonadRec monad's} {@link Pure} instance
216+
* @param <R> the input type
217+
* @param <M> the returned {@link Monad}
218+
* @param <A> the embedded output type
214219
* @return the {@link ReaderT}
215220
*/
216221
public static <R, M extends MonadRec<?, M>, A> ReaderT<R, M, A> readerT(
217-
Fn1<? super R, ? extends MonadRec<A, M>> fn) {
218-
return new ReaderT<>(fn);
222+
Fn1<? super R, ? extends MonadRec<A, M>> fn, Pure<M> pureM) {
223+
return new ReaderT<>(pureM, fn);
219224
}
220225

221226
/**
@@ -230,7 +235,7 @@ public static <R, M extends MonadRec<?, M>, A> ReaderT<R, M, A> readerT(
230235
return new Pure<ReaderT<R, M, ?>>() {
231236
@Override
232237
public <A> ReaderT<R, M, A> checkedApply(A a) {
233-
return readerT(__ -> pureM.apply(a));
238+
return readerT(__ -> pureM.apply(a), pureM);
234239
}
235240
};
236241
}
@@ -245,7 +250,7 @@ public <A> ReaderT<R, M, A> checkedApply(A a) {
245250
return new Lift<ReaderT<R, ?, ?>>() {
246251
@Override
247252
public <A, M extends MonadRec<?, M>> ReaderT<R, M, A> checkedApply(MonadRec<A, M> ga) {
248-
return readerT(constantly(ga));
253+
return readerT(constantly(ga), Pure.of(ga));
249254
}
250255
};
251256
}

src/test/java/com/jnape/palatable/lambda/monad/transformer/builtin/ReaderTTest.java

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,18 @@
88
import com.jnape.palatable.traitor.runners.Traits;
99
import org.junit.Test;
1010
import org.junit.runner.RunWith;
11-
import testsupport.traits.*;
11+
import testsupport.traits.ApplicativeLaws;
12+
import testsupport.traits.Equivalence;
13+
import testsupport.traits.FunctorLaws;
14+
import testsupport.traits.MonadLaws;
15+
import testsupport.traits.MonadReaderLaws;
16+
import testsupport.traits.MonadRecLaws;
1217

1318
import java.util.concurrent.CountDownLatch;
1419
import java.util.concurrent.Executors;
1520

1621
import static com.jnape.palatable.lambda.adt.Maybe.just;
22+
import static com.jnape.palatable.lambda.adt.Maybe.pureMaybe;
1723
import static com.jnape.palatable.lambda.adt.Unit.UNIT;
1824
import static com.jnape.palatable.lambda.functor.builtin.Identity.pureIdentity;
1925
import static com.jnape.palatable.lambda.io.IO.io;
@@ -26,37 +32,37 @@ public class ReaderTTest {
2632

2733
@TestTraits({FunctorLaws.class, ApplicativeLaws.class, MonadLaws.class, MonadReaderLaws.class, MonadRecLaws.class})
2834
public Equivalence<ReaderT<Integer, Identity<?>, Integer>> testSubject() {
29-
return equivalence(readerT(Identity::new), readerT -> readerT.runReaderT(1));
35+
return equivalence(readerT(Identity::new, pureIdentity()), readerT -> readerT.runReaderT(1));
3036
}
3137

3238
@Test
3339
public void profunctor() {
3440
assertEquals(new Identity<>(4),
35-
ReaderT.<Integer, Identity<?>, Integer>readerT(Identity::new)
41+
ReaderT.<Integer, Identity<?>, Integer>readerT(Identity::new, pureIdentity())
3642
.diMap(String::length, x -> x + 1)
3743
.runReaderT("123"));
3844
}
3945

4046
@Test
4147
public void local() {
4248
assertEquals(new Identity<>(2),
43-
ReaderT.<Integer, Identity<?>, Integer>readerT(Identity::new)
49+
ReaderT.<Integer, Identity<?>, Integer>readerT(Identity::new, pureIdentity())
4450
.local(x -> x + 1)
4551
.runReaderT(1));
4652
}
4753

4854
@Test
4955
public void mapReaderT() {
5056
assertEquals(just(3),
51-
ReaderT.<String, Identity<?>, String>readerT(Identity::new)
52-
.<Identity<String>, Maybe<?>, Integer>mapReaderT(id -> just(id.runIdentity().length()))
57+
ReaderT.<String, Identity<?>, String>readerT(Identity::new, pureIdentity())
58+
.<Identity<String>, Maybe<?>, Integer>mapReaderT(id -> just(id.runIdentity().length()), pureMaybe())
5359
.runReaderT("foo"));
5460
}
5561

5662
@Test
5763
public void andComposesLeftToRight() {
58-
ReaderT<Integer, Identity<?>, Float> intToFloat = readerT(x -> new Identity<>(x.floatValue()));
59-
ReaderT<Float, Identity<?>, Double> floatToDouble = readerT(f -> new Identity<>(f.doubleValue()));
64+
ReaderT<Integer, Identity<?>, Float> intToFloat = readerT(x -> new Identity<>(x.floatValue()), pureIdentity());
65+
ReaderT<Float, Identity<?>, Double> floatToDouble = readerT(f -> new Identity<>(f.doubleValue()), pureIdentity());
6066

6167
assertEquals(new Identity<>(1.),
6268
intToFloat.and(floatToDouble).runReaderT(1));

0 commit comments

Comments
 (0)