Merge pull request #38 from kemitix/either
Add `Either<L,R>` and add `TypeAlias<T>.flatMap()`
This commit is contained in:
commit
a53db86452
9 changed files with 1210 additions and 556 deletions
|
@ -2,6 +2,7 @@ CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
0.11.0
|
0.11.0
|
||||||
|
------
|
||||||
|
|
||||||
* Rename `Result.maybeThen()` as `Result.flatMapMaybe()`
|
* Rename `Result.maybeThen()` as `Result.flatMapMaybe()`
|
||||||
* Add `Maybe.match(Consumer,Runnable)`
|
* Add `Maybe.match(Consumer,Runnable)`
|
||||||
|
@ -9,6 +10,8 @@ CHANGELOG
|
||||||
* Add `Maybe.isNothing()`
|
* Add `Maybe.isNothing()`
|
||||||
* BUG: `Maybe.orElseThrow()` now returns value when a Just
|
* BUG: `Maybe.orElseThrow()` now returns value when a Just
|
||||||
* Rewrite README
|
* Rewrite README
|
||||||
|
* Add `Either` (experimental)
|
||||||
|
* Add `flatMap` to `TypeAlias`
|
||||||
|
|
||||||
0.10.0
|
0.10.0
|
||||||
------
|
------
|
||||||
|
|
1333
README.org
1333
README.org
File diff suppressed because it is too large
Load diff
|
@ -30,7 +30,6 @@ import java.util.function.Function;
|
||||||
* for the type being aliased.</p>
|
* for the type being aliased.</p>
|
||||||
*
|
*
|
||||||
* @param <T> the type of the alias
|
* @param <T> the type of the alias
|
||||||
*
|
|
||||||
* @author Paul Campbell (pcampbell@kemitix.net)
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("abstractclassname")
|
@SuppressWarnings("abstractclassname")
|
||||||
|
@ -55,13 +54,24 @@ public abstract class TypeAlias<T> {
|
||||||
*
|
*
|
||||||
* @param f the function to create the new value
|
* @param f the function to create the new value
|
||||||
* @param <R> the type of the new value
|
* @param <R> the type of the new value
|
||||||
*
|
* @return the result of the function
|
||||||
* @return a TypeAlias
|
|
||||||
*/
|
*/
|
||||||
public final <R> R map(final Function<T, R> f) {
|
public final <R> R map(final Function<T, R> f) {
|
||||||
return f.apply(value);
|
return f.apply(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the TypeAlias into another TypeAlias.
|
||||||
|
*
|
||||||
|
* @param f the function to create the new value
|
||||||
|
* @param <R> the type of the new value within a TypeAlias
|
||||||
|
* @param <U> the type of the TypeAlias superclass containing the new value
|
||||||
|
* @return a TypeAlias
|
||||||
|
*/
|
||||||
|
public final <R, U extends TypeAlias<R>> U flatMap(final Function<T, U> f) {
|
||||||
|
return f.apply(value);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final int hashCode() {
|
public final int hashCode() {
|
||||||
return value.hashCode();
|
return value.hashCode();
|
||||||
|
@ -73,7 +83,7 @@ public abstract class TypeAlias<T> {
|
||||||
final TypeAlias other = (TypeAlias) o;
|
final TypeAlias other = (TypeAlias) o;
|
||||||
final Class<?> otherValueClass = other.value.getClass();
|
final Class<?> otherValueClass = other.value.getClass();
|
||||||
return otherValueClass.equals(getValue().getClass())
|
return otherValueClass.equals(getValue().getClass())
|
||||||
&& other.value.equals(getValue());
|
&& other.value.equals(getValue());
|
||||||
}
|
}
|
||||||
return map(o::equals);
|
return map(o::equals);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,99 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon.experimental.either;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Either type for holding a one of two possible values, a left and a right, that may be of different types.
|
||||||
|
*
|
||||||
|
* @param <L> the type of the Either for left value
|
||||||
|
* @param <R> the type of the Either for right value
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
public interface Either<L, R> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Either holding a left value.
|
||||||
|
*
|
||||||
|
* @param l the left value
|
||||||
|
* @param <L> the type of the left value
|
||||||
|
* @param <R> the type of the right value
|
||||||
|
* @return a Either holding the left value
|
||||||
|
*/
|
||||||
|
static <L, R> Either<L, R> left(final L l) {
|
||||||
|
return new Left<>(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Either holding a right value.
|
||||||
|
*
|
||||||
|
* @param r the right value
|
||||||
|
* @param <L> the type of the left value
|
||||||
|
* @param <R> the type of the right value
|
||||||
|
* @return a Either holding the right value
|
||||||
|
*/
|
||||||
|
static <L, R> Either<L, R> right(final R r) {
|
||||||
|
return new Right<>(r);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the Either holds a left value.
|
||||||
|
*
|
||||||
|
* @return true if this Either is a left
|
||||||
|
*/
|
||||||
|
boolean isLeft();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the Either holds a right value.
|
||||||
|
*
|
||||||
|
* @return true if this Either is a right
|
||||||
|
*/
|
||||||
|
boolean isRight();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Matches the Either, invoking the correct Consumer.
|
||||||
|
*
|
||||||
|
* @param onLeft the Consumer to invoke when the Either is a left
|
||||||
|
* @param onRight the Consumer to invoke when the Either is a right
|
||||||
|
*/
|
||||||
|
void match(Consumer<L> onLeft, Consumer<R> onRight);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the function across the left value.
|
||||||
|
*
|
||||||
|
* @param f the function to apply to any left value
|
||||||
|
* @param <T> the type to change the left value to
|
||||||
|
* @return a new Either
|
||||||
|
*/
|
||||||
|
<T> Either<T, R> mapLeft(Function<L, T> f);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map the function across the right value.
|
||||||
|
*
|
||||||
|
* @param f the function to apply to any right value
|
||||||
|
* @param <T> the type to change the right value to
|
||||||
|
* @return a new Either
|
||||||
|
*/
|
||||||
|
<T> Either<L, T> mapRight(Function<R, T> f);
|
||||||
|
}
|
61
src/main/java/net/kemitix/mon/experimental/either/Left.java
Normal file
61
src/main/java/net/kemitix/mon/experimental/either/Left.java
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon.experimental.either;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Either type holding a left value.
|
||||||
|
*
|
||||||
|
* @param <L> the type of the Either for left value
|
||||||
|
* @param <R> the type of the Either for right value
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
class Left<L, R> implements Either<L, R> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final boolean left = true;
|
||||||
|
@Getter
|
||||||
|
private final boolean right = false;
|
||||||
|
|
||||||
|
private final L value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void match(final Consumer<L> onLeft, final Consumer<R> onRight) {
|
||||||
|
onLeft.accept(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Either<T, R> mapLeft(final Function<L, T> f) {
|
||||||
|
return new Left<>(f.apply(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Either<L, T> mapRight(final Function<R, T> f) {
|
||||||
|
return new Left<>(value);
|
||||||
|
}
|
||||||
|
}
|
61
src/main/java/net/kemitix/mon/experimental/either/Right.java
Normal file
61
src/main/java/net/kemitix/mon/experimental/either/Right.java
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon.experimental.either;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An Either type holding a right value.
|
||||||
|
*
|
||||||
|
* @param <L> the type of the Either for left value
|
||||||
|
* @param <R> the type of the Either for right value
|
||||||
|
* @author Paul Campbell (pcampbell@kemitix.net)
|
||||||
|
*/
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
class Right<L, R> implements Either<L, R> {
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final boolean left = false;
|
||||||
|
@Getter
|
||||||
|
private final boolean right = true;
|
||||||
|
|
||||||
|
private final R value;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void match(final Consumer<L> onLeft, final Consumer<R> onRight) {
|
||||||
|
onRight.accept(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Either<T, R> mapLeft(final Function<L, T> f) {
|
||||||
|
return new Right<>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T> Either<L, T> mapRight(final Function<R, T> f) {
|
||||||
|
return new Right<>(f.apply(value));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* The MIT License (MIT)
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017 Paul Campbell
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
||||||
|
* and associated documentation files (the "Software"), to deal in the Software without restriction,
|
||||||
|
* including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all copies
|
||||||
|
* or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||||
|
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||||
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.kemitix.mon.experimental.either;
|
114
src/test/java/net/kemitix/mon/EitherTest.java
Normal file
114
src/test/java/net/kemitix/mon/EitherTest.java
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import net.kemitix.mon.experimental.either.Either;
|
||||||
|
import org.assertj.core.api.WithAssertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class EitherTest implements WithAssertions {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLeft_isLeft() {
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> either = Either.left(1);
|
||||||
|
//then
|
||||||
|
assertThat(either.isLeft()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLeft_isNotRight() {
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> either = Either.left(1);
|
||||||
|
//then
|
||||||
|
assertThat(either.isRight()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRight_isNotLeft() {
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> either = Either.right("1");
|
||||||
|
//then
|
||||||
|
assertThat(either.isLeft()).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRight_isRight() {
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> either = Either.right("1");
|
||||||
|
//then
|
||||||
|
assertThat(either.isRight()).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenLeft_matchLeft() {
|
||||||
|
//given
|
||||||
|
final Either<Integer, String> either = Either.left(1);
|
||||||
|
//then
|
||||||
|
either.match(
|
||||||
|
left -> assertThat(left).isEqualTo(1),
|
||||||
|
right -> fail("Not a right")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenRight_matchRight() {
|
||||||
|
//given
|
||||||
|
final Either<Integer, String> either = Either.right("1");
|
||||||
|
//then
|
||||||
|
either.match(
|
||||||
|
left -> fail("Not a left"),
|
||||||
|
right -> assertThat(right).isEqualTo("1")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLeft_whenMapLeft_thenMap() {
|
||||||
|
//given
|
||||||
|
final Either<Integer, String> either = Either.left(2);
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> result = either.mapLeft(l -> l * 2);
|
||||||
|
//then
|
||||||
|
result.match(
|
||||||
|
left -> assertThat(left).isEqualTo(4),
|
||||||
|
right -> fail("Not a right")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenRight_whenMapRight_thenMap() {
|
||||||
|
//given
|
||||||
|
final Either<Integer, String> either = Either.right("2");
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> result = either.mapRight(l -> l + "2");
|
||||||
|
//then
|
||||||
|
result.match(
|
||||||
|
left -> fail("Not a left"),
|
||||||
|
right -> assertThat(right).isEqualTo("22")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLeft_whenMapRight_thenDoNothing() {
|
||||||
|
//given
|
||||||
|
final Either<Integer, String> either = Either.left(2);
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> result = either.mapRight(r -> r + "x");
|
||||||
|
//then
|
||||||
|
result.match(
|
||||||
|
left -> assertThat(left).isEqualTo(2),
|
||||||
|
right -> fail("Not a right")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenRight_whenMapLeft_thenDoNothing() {
|
||||||
|
//given
|
||||||
|
final Either<Integer, String> either = Either.right("2");
|
||||||
|
//when
|
||||||
|
final Either<Integer, String> result = either.mapLeft(l -> l * 2);
|
||||||
|
//then
|
||||||
|
result.match(
|
||||||
|
left -> fail("Not a left"),
|
||||||
|
right -> assertThat(right).isEqualTo("2")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
55
src/test/java/net/kemitix/mon/TypeAliasMonadTest.java
Normal file
55
src/test/java/net/kemitix/mon/TypeAliasMonadTest.java
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package net.kemitix.mon;
|
||||||
|
|
||||||
|
import org.assertj.core.api.WithAssertions;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public class TypeAliasMonadTest implements WithAssertions {
|
||||||
|
|
||||||
|
private final int v = 1;
|
||||||
|
private final Function<Integer, AnAlias<Integer>> f = i -> a(i * 2);
|
||||||
|
private final Function<Integer, AnAlias<Integer>> g = i -> a(i + 6);
|
||||||
|
|
||||||
|
private static AnAlias<Integer> a(Integer v) {
|
||||||
|
return AnAlias.of(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void leftIdentity() {
|
||||||
|
assertThat(
|
||||||
|
a(v).flatMap(f)
|
||||||
|
).isEqualTo(
|
||||||
|
f.apply(v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void rightIdentity() {
|
||||||
|
final AnAlias<Integer> integerAnAlias = a(v).flatMap(x -> a(x));
|
||||||
|
assertThat(
|
||||||
|
integerAnAlias
|
||||||
|
).isEqualTo(
|
||||||
|
a(v)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void associativity() {
|
||||||
|
assertThat(
|
||||||
|
a(v).flatMap(f).flatMap(g)
|
||||||
|
).isEqualTo(
|
||||||
|
a(v).flatMap(x -> f.apply(x).flatMap(g))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class AnAlias<T> extends TypeAlias<T> {
|
||||||
|
private AnAlias(T value) {
|
||||||
|
super(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> AnAlias<T> of(T value) {
|
||||||
|
return new AnAlias<>(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue