Maybe satisfies the three Monad Laws
This commit is contained in:
parent
2211182c7d
commit
5d39be36ff
6 changed files with 103 additions and 0 deletions
|
@ -55,6 +55,8 @@ class Example {
|
|||
|
||||
### Maybe
|
||||
|
||||
A Monad.
|
||||
|
||||
A non-final substitute for Optional with `peek()` and `stream()` methods.
|
||||
|
||||
```java
|
||||
|
|
|
@ -43,6 +43,11 @@ final class Just<T> implements Maybe<T> {
|
|||
|
||||
private final T value;
|
||||
|
||||
@Override
|
||||
public <R> Maybe<R> flatMap(Function<T, Maybe<R>> f) {
|
||||
return f.apply(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> Maybe<R> map(final Function<T, R> f) {
|
||||
return new Just<>(f.apply(value));
|
||||
|
|
|
@ -76,6 +76,15 @@ public interface Maybe<T> extends Functor<T, Maybe<?>> {
|
|||
return new Just<>(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Monad binder maps the Maybe into another Maybe using the binder method f.
|
||||
*
|
||||
* @param f the mapper function
|
||||
* @param <R> the type of the value in the final maybe
|
||||
* @return a Maybe with the mapped value
|
||||
*/
|
||||
<R> Maybe<R> flatMap(Function<T, Maybe<R>> f);
|
||||
|
||||
@Override
|
||||
<R> Maybe<R> map(Function<T, R> f);
|
||||
|
||||
|
|
|
@ -38,6 +38,11 @@ final class Nothing<T> implements Maybe<T> {
|
|||
|
||||
static final Maybe<?> INSTANCE = new Nothing<>();
|
||||
|
||||
@Override
|
||||
public <R> Maybe<R> flatMap(Function<T, Maybe<R>> f) {
|
||||
return Maybe.nothing();
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <R> Maybe<R> map(final Function<T, R> f) {
|
||||
|
|
39
src/test/java/net/kemitix/mon/MaybeMonadTest.java
Normal file
39
src/test/java/net/kemitix/mon/MaybeMonadTest.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
package net.kemitix.mon;
|
||||
|
||||
import net.kemitix.mon.maybe.Maybe;
|
||||
import org.assertj.core.api.WithAssertions;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class MaybeMonadTest implements WithAssertions {
|
||||
|
||||
@Test
|
||||
public void leftIdentity() {
|
||||
//given
|
||||
final int value = 1;
|
||||
final Maybe<Integer> maybe = Maybe.maybe(value);
|
||||
final Function<Integer, Maybe<Integer>> f = i -> Maybe.maybe(i * 2);
|
||||
//then
|
||||
assertThat(maybe.flatMap(f)).isEqualTo(f.apply(value));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rightIdentity() {
|
||||
//given
|
||||
final Maybe<Integer> maybe = Maybe.maybe(1);
|
||||
//then
|
||||
assertThat(maybe.flatMap(Maybe::maybe)).isEqualTo(maybe);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void associativity() {
|
||||
//given
|
||||
final Maybe<Integer> maybe = Maybe.maybe(1);
|
||||
final Function<Integer, Maybe<Integer>> f = i -> Maybe.maybe(i * 2);
|
||||
final Function<Integer, Maybe<Integer>> g = i -> Maybe.maybe(i + 6);
|
||||
//then
|
||||
assertThat(maybe.flatMap(f).flatMap(g)).isEqualTo(maybe.flatMap(x -> f.apply(x).flatMap(g)));
|
||||
}
|
||||
|
||||
}
|
|
@ -123,4 +123,47 @@ public class MaybeTest implements WithAssertions {
|
|||
//then
|
||||
assertThat(stream).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void justFlatMap() {
|
||||
//given
|
||||
final Maybe<Integer> just1 = Maybe.just(1);
|
||||
final Maybe<Integer> just2 = Maybe.just(2);
|
||||
//when
|
||||
final Maybe<Integer> result = just1.flatMap(v1 ->
|
||||
just2.flatMap(v2 ->
|
||||
Maybe.maybe(v1 + v2)
|
||||
));
|
||||
//then
|
||||
assertThat(result.toOptional()).contains(3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nothingFlatMap() {
|
||||
//given
|
||||
final Maybe<Integer> nothing1 = Maybe.nothing();
|
||||
final Maybe<Integer> nothing2 = Maybe.nothing();
|
||||
//when
|
||||
final Maybe<Integer> result = nothing1.flatMap(v1 ->
|
||||
nothing2.flatMap(v2 ->
|
||||
Maybe.maybe(v1 + v2)
|
||||
));
|
||||
//then
|
||||
assertThat(result.toOptional()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void justNothingFlatMap() {
|
||||
//given
|
||||
final Maybe<Integer> just1 = Maybe.just(1);
|
||||
final Maybe<Integer> nothing2 = Maybe.nothing();
|
||||
//when
|
||||
final Maybe<Integer> result = just1.flatMap(v1 ->
|
||||
nothing2.flatMap(v2 ->
|
||||
Maybe.maybe(v1 + v2)
|
||||
));
|
||||
//then
|
||||
assertThat(result.toOptional()).isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue