Skip to content

Commit d81d235

Browse files
committed
Adding ReaderT#and, category composition between ReaderTs
1 parent 75b1fb7 commit d81d235

File tree

3 files changed

+23
-6
lines changed

3 files changed

+23
-6
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/).
1414
- `Id#id` overload that accepts an argument and returns it
1515
- `MaybeT#or`, choose the first `MaybeT` that represents an effect around `just` a value
1616
- `StateMatcher, StateTMatcher, WriterTMatcher`
17+
- `ReaderT#and`, category composition between `ReaderT` instances: `(a -> m b) -> (b -> m c) -> (a -> m c)`
1718

1819
## [5.1.0] - 2019-10-13
1920
### Changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ public <MA extends MonadRec<A, M>, N extends MonadRec<?, N>, B> ReaderT<R, N, B>
6161
return readerT(r -> fn.apply(runReaderT(r).coerce()));
6262
}
6363

64+
/**
65+
* Left-to-right composition between {@link ReaderT} instances running under the same effect and compatible between
66+
* their inputs and outputs.
67+
*
68+
* @param amb the next {@link ReaderT} to run
69+
* @param <B> the final output type
70+
* @return the composed {@link ReaderT}
71+
*/
72+
public <B> ReaderT<R, M, B> and(ReaderT<A, M, B> amb) {
73+
return readerT(r -> runReaderT(r).flatMap(amb::runReaderT));
74+
}
75+
6476
/**
6577
* {@inheritDoc}
6678
*/

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@
88
import com.jnape.palatable.traitor.runners.Traits;
99
import org.junit.Test;
1010
import org.junit.runner.RunWith;
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;
11+
import testsupport.traits.*;
1712

1813
import java.util.concurrent.CountDownLatch;
1914
import java.util.concurrent.Executors;
@@ -58,6 +53,15 @@ public void mapReaderT() {
5853
.runReaderT("foo"));
5954
}
6055

56+
@Test
57+
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()));
60+
61+
assertEquals(new Identity<>(1.),
62+
intToFloat.and(floatToDouble).runReaderT(1));
63+
}
64+
6165
@Test
6266
public void staticPure() {
6367
ReaderT<String, Identity<?>, Integer> readerT =

0 commit comments

Comments
 (0)