Skip to content

Instantly share code, notes, and snippets.

@andimiller
Created July 24, 2019 11:52
Show Gist options
  • Save andimiller/9c6a6472a43f2d3d546c7fe4605d4416 to your computer and use it in GitHub Desktop.
Save andimiller/9c6a6472a43f2d3d546c7fe4605d4416 to your computer and use it in GitHub Desktop.
import java.util.function.Function;
import java.util.Optional;
class Result<L, R> {
enum State {
Left,
Right
}
private final State state;
private final Optional<L> left;
private final Optional<R> right;
private Result(State state, Optional<L> left, Optional<R> right) {
this.state = state;
this.left = left;
this.right = right;
}
Optional<L> errorToOption() {
return left;
}
Optional<R> toOption() {
return right;
}
Boolean isError() {
return state == State.Left;
}
Boolean isSuccess() {
return state == State.Right;
}
public <R2> Result<L, R2> map(Function<R, R2> f) {
return new Result<L, R2>(state, left, right.map(f));
}
public <L2> Result<L2, R> errorMap(Function<L, L2> f) {
return new Result<L2, R>(state, left.map(f), right);
}
public <T> T fold(Function<L, T> lf, Function<R, T> rf) {
switch (state) {
case Left:
return left.map(lf).get();
case Right:
return right.map(rf).get();
}
throw new RuntimeException("java's compiler sucks so it can't tell this will never happen");
}
public <L2, R2> Result<L2, R2> bimap(Function<L, L2> lf, Function<R, R2> rf) {
return new Result<L2, R2>(state, left.map(lf), right.map(rf))
}
/// can we also be a monad?
// here's normal flatMap
public <R2> Result<L, R2> flatMap(Function<R, Result<L, R2>> f) {
switch (state) {
case Left:
// I can safely cast the Void, dw about it
return (Result<L, R2>) Result.ofError(left.get());
case Right:
return f.apply(right.get());
}
throw new RuntimeException("seriously it's an exhaustive switch, fuck off");
}
// and here's the flatMap where our result has no error
public <R2> Result<L, R2> flatMap(Function<R, Result<Void, R2>> f) {
switch (state) {
case Left:
// I can safely cast the Void, dw about it
return (Result<L, R2>) Result.ofError(left.get());
case Right:
return (Result<L, R2>) Result.of(f.apply(right.get()).right.get());
}
throw new RuntimeException("seriously it's an exhaustive switch, fuck off");
}
// and here's the flatMap where our result has no success
public Result<L, R> flatMap(Function<R, Result<L, Void>> f) {
switch (state) {
case Left:
// I can safely cast the Void, dw about it
return (Result<L, R>) Result.ofError(left.get());
case Right:
return (Result<L, R>) Result.ofError(f.apply(right.get()).left.get());
}
throw new RuntimeException("seriously it's an exhaustive switch, fuck off");
}
// constructors!
static <L> Result<L, Void> ofError(L e) {
return new Result<L, Void>(State.Left, Optional.of(e), Optional.empty());
}
static <R> Result<Void, R> of(R r) {
return new Result<Void, R>(State.Right, Optional.empty(), Optional.of(r));
}
// examples
public static void main(String[] args) {
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment