Skip to content

Instantly share code, notes, and snippets.

@juanmc2005
Last active May 8, 2017 15:37
Show Gist options
  • Save juanmc2005/4c5938d1e454c9d20b37320e0b7c29d3 to your computer and use it in GitHub Desktop.
Save juanmc2005/4c5938d1e454c9d20b37320e0b7c29d3 to your computer and use it in GitHub Desktop.
public interface Action {
void run();
}
public interface BiFunction<A, B, C> {
C apply(A x, B y);
}
public interface Consumer<T> {
void apply(T x);
}
public class Either<L, R> {
public static <L, R> Either<L, R> left(L value) {
return new Either<>(Option.just(value), Option.none());
}
public static <L, R> Either<L, R> right(R value) {
return new Either<>(Option.none(), Option.just(value));
}
private final Option<L> valueLeft;
private final Option<R> valueRight;
private Either(Option<L> valueLeft, Option<R> valueRight) {
this.valueLeft = valueLeft;
this.valueRight = valueRight;
}
public boolean isLeft() {
return valueLeft.isPresent();
}
public boolean isRight() {
return valueRight.isPresent();
}
public <T> Either<T, R> mapLeft(Function<L, T> f) {
if (isLeft()) return left(f.apply(valueLeft.get()));
else return right(valueRight.get());
}
public <T> Either<L, T> mapRight(Function<R, T> f) {
if (isRight()) return right(f.apply(valueRight.get()));
else return left(valueLeft.get());
}
public <T> Option<T> flatMapOption(Function<L, T> f1, Function<R, T> f2) {
if (isLeft()) return Option.just(f1.apply(valueLeft.get()));
else return Option.just(f2.apply(valueRight.get()));
}
}
public interface Function<T, R> {
R apply(T x);
}
public final class Lists {
private Lists() {
throw new IllegalAccessError("Cannot instantiate Lists");
}
public static <A, B> List<B> map(final List<A> xs, final Function<A, B> f) {
final List<B> result = new ArrayList<>();
for (A a : xs) result.add(f.apply(a));
return result;
}
public static <A> List<A> filter(final List<A> xs, final Function<A, Boolean> f) {
final List<A> result = new ArrayList<>();
for (A a : xs) if (f.apply(a)) result.add(a);
return result;
}
public static <A> List<A> flatten(final List<List<A>> xss) {
final List<A> result = new ArrayList<>();
for (List<A> xs : xss) for (A x : xs) result.add(x);
return result;
}
public static <A, B> List<B> flatMap(final List<A> xs, final Function<A, List<B>> f) {
return flatten(map(xs, f));
}
public static <A, B> B fold(final B acc, final List<A> xs, final BiFunction<A, B, B> f) {
B result = acc;
for (A x : xs) result = f.apply(x, result);
return result;
}
public static <A, B> B interruptedFold(final B acc, List<A> xs, final BiFunction<A, B, Pair<Boolean, B>> f) {
B result = acc;
for (A x : xs) {
Pair<Boolean, B> pair = f.apply(x, result);
result = pair.second;
if (!pair.first) return result;
}
return result;
}
public static <A> Option<A> find(final List<A> xs, final Function<A, Boolean> f) {
return interruptedFold(Option.none(), xs, (x, opt) ->
f.apply(x)
? new Pair<>(false, Option.just(x))
: new Pair<>(true, Option.none()));
}
public static <A> List<A> cons(final A x, final List<A> xs) {
xs.add(0, x);
return xs;
}
public static <A> Pair<List<A>, List<A>> split(final List<A> xs, final Function<A, Boolean> f) {
final List<A> first = new ArrayList<>();
final List<A> second = new ArrayList<>();
for (A x : xs) (f.apply(x) ? first : second).add(x);
return new Pair<>(first, second);
}
}
public class Option<T> {
public static <A> Option<A> just(A a) {
return new Option<>(a);
}
public static <A> Option<A> none() {
return Option.just(null);
}
private final T value;
private Option(T value) {
this.value = value;
}
public T get() {
if (value != null) return value;
else throw new IllegalStateException("Cannot call get() on None");
}
public T getOrElse(T something) {
if (isPresent()) return value;
else return something;
}
public Option<T> doIfPresent(Consumer<T> consumer) {
if (isPresent()) consumer.apply(value);
return this;
}
public Option<T> doIfNotPresent(Action action) {
if (!isPresent()) action.run();
return this;
}
public Option<T> doIfElse(Consumer<T> consumer, Action action) {
if (isPresent()) consumer.apply(value);
else action.run();
return this;
}
public <A> Option<A> mapIfElse(Function<T, A> f, Producer<A> g) {
if (isPresent()) return new Option<>(f.apply(value));
else return Option.just(g.produce());
}
public boolean isPresent() {
return value != null;
}
public <A> Option<A> map(Function<T, A> f) {
if (isPresent()) return Option.just(f.apply(value));
else return Option.none();
}
public Option<T> filter(Function<T, Boolean> f) {
if (isPresent() && f.apply(value)) return Option.just(value);
else return Option.none();
}
public <A> Option<A> flatMap(Function<T, Option<A>> f) {
final Option<A> option = f.apply(value);
if (option.isPresent()) return Option.just(option.get());
else return Option.none();
}
}
public interface Producer<T> {
T produce();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment