diff --git a/README.md b/README.md
index fc539ca..3c60ed3 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,8 @@ https://oss.sonatype.org/content/repositories/releases/net/kemitix/mon/)
https://img.shields.io/maven-central/v/net.kemitix/mon.svg?style=for-the-badge)](
https://search.maven.org/artifact/net.kemitix/mon)
+The documentation below is being slowly migrated to [Javadoc](https://kemitix.github.io/mon/).
+
- [Maven Usage](#Maven-Usage)
- [Wrapper](#Wrapper) - light-weight type-alias-like
- [TypeAlias](#TypeAlias) - type-alias-like monadic wrapper
diff --git a/pom.xml b/pom.xml
index e5857a4..ad2f0fe 100644
--- a/pom.xml
+++ b/pom.xml
@@ -11,7 +11,7 @@
mon
- 3.2.0
+ 3.3.0
Mon
Wrapper, TypeAlias, Maybe, Result, Tree, Lazy, Either and Combinators for Java.
diff --git a/src/main/java/net/kemitix/mon/reader/Reader.java b/src/main/java/net/kemitix/mon/reader/Reader.java
index 4ae091b..c54f2ae 100644
--- a/src/main/java/net/kemitix/mon/reader/Reader.java
+++ b/src/main/java/net/kemitix/mon/reader/Reader.java
@@ -44,7 +44,21 @@ public interface Reader {
* @return a new Reader to provided the result of the supplied function
*/
@API(status = API.Status.EXPERIMENTAL)
- default Reader andThen(BiFunction f) {
+ default Reader flatMap(BiFunction f) {
return env -> f.apply(env, run(env));
}
+
+ /**
+ * Applies the function provided to the reader when run, and executes that
+ * resulting reader.
+ *
+ * @param f the function which takes the previously generated value and
+ * produces another Reader
+ * @param the type of the value the new Reader returns
+ * @return a new Reader
+ */
+ @API(status = API.Status.EXPERIMENTAL)
+ default Reader flatMap(Function> f) {
+ return env -> f.apply(run(env)).run(env);
+ }
}
diff --git a/src/test/java/net/kemitix/mon/ReaderTest.java b/src/test/java/net/kemitix/mon/ReaderTest.java
index 5313dd0..14dd0ea 100644
--- a/src/test/java/net/kemitix/mon/ReaderTest.java
+++ b/src/test/java/net/kemitix/mon/ReaderTest.java
@@ -6,6 +6,7 @@ import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Function;
public class ReaderTest
implements WithAssertions {
@@ -66,8 +67,8 @@ public class ReaderTest
};
Reader program =
((Reader) e -> e.intValue())
- .andThen((e, i) -> e.intValue() + (i * 2))
- .andThen((e, i) -> String.format("%.2f",
+ .flatMap((e, i) -> e.intValue() + (i * 2))
+ .flatMap((e, i) -> String.format("%.2f",
i.floatValue() / e.intValue()));
//when
String result = program.run(env);
@@ -75,6 +76,32 @@ public class ReaderTest
assertThat(result).isEqualTo("2.96");// ((123 * 2) + (123 + 1)) / (123 + 2)
}
+ @Test
+ @DisplayName("flatMap")
+ void flatMap() {
+ //given
+ AtomicInteger value = new AtomicInteger(123);
+ Environment env = new Environment() {
+ @Override
+ public Integer intValue() {
+ return value.incrementAndGet();
+ }
+ };
+ Function> addNextValue =
+ integer -> (Reader) e -> e.intValue() + integer;
+ Function> divideByNextValue =
+ integer -> (Reader) e -> integer.floatValue() / e.intValue();
+ Reader program =
+ ((Reader) e -> e.intValue())
+ .flatMap(addNextValue)
+ .flatMap(divideByNextValue)
+ .map(f -> String.format("%.3f", f));
+ //when
+ String result = program.run(env);
+ //then
+ assertThat(result).isEqualTo("1.976");// (123 + 124) / 125
+ }
+
private interface Environment {
Integer intValue();