Last active
February 9, 2017 07:03
-
-
Save jbgi/d6035910e55b5b45d1e18553530d9d72 to your computer and use it in GitHub Desktop.
Minimal Either in Java with Derive4J
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.function.Function; | |
import org.derive4j.Data; | |
@Data | |
interface Either<A, B> { | |
<X> X match(Function<A, X> left, Function<B, X> right); | |
static void main(String[] args) { | |
Either<Integer, String> l = Eithers.left(-1); | |
Either<Integer, String> r = Eithers.right("Ok"); | |
Function<Either<Integer, String>, String> toString = Eithers.<Integer, String> | |
cases() | |
.left(String::valueOf) | |
.right(Function.identity()); | |
int intValue = Eithers. | |
caseOf(l) | |
.left(Function.identity()) | |
.right(String::length); | |
int intValue2 = r.match(left -> left, right -> right.length()); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// GENERATED File for the above: | |
import java.lang.Override; | |
import java.lang.SuppressWarnings; | |
import java.util.Optional; | |
import java.util.function.Function; | |
import java.util.function.Supplier; | |
public final class Eithers { | |
private Eithers() { | |
} | |
public static <A, B> Either<A, B> left(A left) { | |
return new Left<>(left); | |
} | |
public static <A, B> Either<A, B> right(B right) { | |
return new Right<>(right); | |
} | |
public static <A, B> Either<A, B> lazy(Supplier<Either<A, B>> either) { | |
return new Lazy<>(either); | |
} | |
@SuppressWarnings("unchecked") | |
public static <A, B> CasesMatchers.TotalMatcher_Left<A, B> cases() { | |
return (CasesMatchers.TotalMatcher_Left<A, B>) CasesMatchers.totalMatcher_Left; | |
} | |
public static <A, B> CaseOfMatchers.TotalMatcher_Left<A, B> caseOf(Either<A, B> either) { | |
return new CaseOfMatchers.TotalMatcher_Left<A, B>(either); | |
} | |
public static <A, B> Optional<A> getLeft(Either<A, B> either) { | |
return either.match((left) -> Optional.of(left), | |
(right) -> Optional.empty());} | |
public static <A, B> Optional<B> getRight(Either<A, B> either) { | |
return either.match((left) -> Optional.empty(), | |
(right) -> Optional.of(right));} | |
public static <A, B, XA> Function<Either<A, B>, Either<XA, B>> setLeft(XA newLeft) { | |
return modLeft(__ -> newLeft); | |
} | |
public static <A, B, XA> Function<Either<A, B>, Either<XA, B>> modLeft(Function<A, XA> leftMod) { | |
return either -> either.match((left) -> left(leftMod.apply(left)), | |
Eithers::right); | |
} | |
public static <A, B, XB> Function<Either<A, B>, Either<A, XB>> setRight(XB newRight) { | |
return modRight(__ -> newRight); | |
} | |
public static <A, B, XB> Function<Either<A, B>, Either<A, XB>> modRight(Function<B, XB> rightMod) { | |
return either -> either.match(Eithers::left, | |
(right) -> right(rightMod.apply(right))); | |
} | |
private static final class Left<A, B> extends Either<A, B> { | |
private final A left; | |
Left(A left) { | |
this.left = left; | |
} | |
@Override | |
public <X> X match(Function<A, X> left, Function<B, X> right) { | |
return left.apply(this.left); | |
} | |
} | |
private static final class Right<A, B> extends Either<A, B> { | |
private final B right; | |
Right(B right) { | |
this.right = right; | |
} | |
@Override | |
public <X> X match(Function<A, X> left, Function<B, X> right) { | |
return right.apply(this.right); | |
} | |
} | |
private static final class Lazy<A, B> extends Either<A, B> { | |
private volatile Supplier<Either<A, B>> expression; | |
private Either<A, B> evaluation; | |
Lazy(Supplier<Either<A, B>> either) { | |
this.expression = either; | |
} | |
private synchronized Either<A, B> _evaluate() { | |
Supplier<Either<A, B>> e = expression; | |
if (e != null) { | |
evaluation = e.get(); | |
expression = null; | |
} | |
return evaluation; | |
} | |
@Override | |
public <X> X match(Function<A, X> left, Function<B, X> right) { | |
return (this.expression == null ? this.evaluation : _evaluate()).match(left, right); | |
} | |
} | |
public static class CasesMatchers { | |
private static final TotalMatcher_Left<?, ?> totalMatcher_Left = new TotalMatcher_Left<>(); | |
private CasesMatchers() { | |
} | |
public static final class TotalMatcher_Left<A, B> { | |
TotalMatcher_Left() { | |
} | |
public final <X> TotalMatcher_Right<A, B, X> left(Function<A, X> left) { | |
return new TotalMatcher_Right<>(left); | |
} | |
public final <X> TotalMatcher_Right<A, B, X> left_(X x) { | |
return this.left((left) -> x); | |
} | |
public final <X> PartialMatcher<A, B, X> right(Function<B, X> right) { | |
return new PartialMatcher<>(null, right); | |
} | |
public final <X> PartialMatcher<A, B, X> right_(X x) { | |
return this.right((right) -> x); | |
} | |
} | |
public static final class TotalMatcher_Right<A, B, X> extends PartialMatcher<A, B, X> { | |
TotalMatcher_Right(Function<A, X> left) { | |
super(left, null); | |
} | |
public final Function<Either<A, B>, X> right(Function<B, X> right) { | |
Function<A, X> left = super.left; | |
return either -> either.match(left, right); | |
} | |
public final Function<Either<A, B>, X> right_(X x) { | |
return this.right((right) -> x); | |
} | |
} | |
public static class PartialMatcher<A, B, X> { | |
private final Function<A, X> left; | |
private final Function<B, X> right; | |
PartialMatcher(Function<A, X> left, Function<B, X> right) { | |
this.left = left; | |
this.right = right; | |
} | |
public final Function<Either<A, B>, X> otherwise(Supplier<X> otherwise) { | |
Function<A, X> left = (this.left != null) ? this.left : (left_) -> otherwise.get(); | |
Function<B, X> right = (this.right != null) ? this.right : (right_) -> otherwise.get(); | |
return either -> either.match(left, right); | |
} | |
public final Function<Either<A, B>, X> otherwise_(X x) { | |
return this.otherwise(() -> x); | |
} | |
public final Function<Either<A, B>, Optional<X>> otherwiseEmpty() { | |
Function<A, Optional<X>> left = (this.left != null) ? (left_) -> Optional.of(this.left.apply(left_)) | |
: (left_) -> Optional.empty(); | |
Function<B, Optional<X>> right = (this.right != null) ? (right_) -> Optional.of(this.right.apply(right_)) | |
: (right_) -> Optional.empty(); | |
return either -> either.match(left, right); | |
} | |
} | |
} | |
public static class CaseOfMatchers { | |
private CaseOfMatchers() { | |
} | |
public static final class TotalMatcher_Left<A, B> { | |
private final Either<A, B> _either; | |
TotalMatcher_Left(Either<A, B> _either) { | |
this._either = _either; | |
} | |
public final <X> TotalMatcher_Right<A, B, X> left(Function<A, X> left) { | |
return new TotalMatcher_Right<>(this._either, left); | |
} | |
public final <X> TotalMatcher_Right<A, B, X> left_(X x) { | |
return this.left((left) -> x); | |
} | |
public final <X> PartialMatcher<A, B, X> right(Function<B, X> right) { | |
return new PartialMatcher<>(this._either, null, right); | |
} | |
public final <X> PartialMatcher<A, B, X> right_(X x) { | |
return this.right((right) -> x); | |
} | |
} | |
public static final class TotalMatcher_Right<A, B, X> extends PartialMatcher<A, B, X> { | |
TotalMatcher_Right(Either<A, B> _either, Function<A, X> left) { | |
super(_either, left, null); | |
} | |
public final X right(Function<B, X> right) { | |
Function<A, X> left = super.left; | |
return ((PartialMatcher<A, B, X>) this)._either.match(left, right); | |
} | |
public final X right_(X x) { | |
return this.right((right) -> x); | |
} | |
} | |
public static class PartialMatcher<A, B, X> { | |
private final Either<A, B> _either; | |
private final Function<A, X> left; | |
private final Function<B, X> right; | |
PartialMatcher(Either<A, B> _either, Function<A, X> left, Function<B, X> right) { | |
this._either = _either; | |
this.left = left; | |
this.right = right; | |
} | |
public final X otherwise(Supplier<X> otherwise) { | |
Function<A, X> left = (this.left != null) ? this.left : (left_) -> otherwise.get(); | |
Function<B, X> right = (this.right != null) ? this.right : (right_) -> otherwise.get(); | |
return this._either.match(left, right); | |
} | |
public final X otherwise_(X x) { | |
return this.otherwise(() -> x); | |
} | |
public final Optional<X> otherwiseEmpty() { | |
Function<A, Optional<X>> left = (this.left != null) ? (left_) -> Optional.of(this.left.apply(left_)) | |
: (left_) -> Optional.empty(); | |
Function<B, Optional<X>> right = (this.right != null) ? (right_) -> Optional.of(this.right.apply(right_)) | |
: (right_) -> Optional.empty(); | |
return this._either.match(left, right); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment