Last active
February 10, 2017 12:26
Revisions
-
rkrzewski revised this gist
Feb 10, 2017 . 1 changed file with 46 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -118,6 +118,52 @@ public static <L, R> Either<L, Stream<R>> sequence(Stream<Either<L, R>> eithers) return eithers.reduce(zero, accumulator, combiner).map(l -> l.stream()); } public static <L, R> Either<Stream<L>, Stream<R>> bisequence(Stream<Either<L, R>> eithers) { Either<List<L>, List<R>> zero = right(new LinkedList<R>()); BiFunction<Either<List<L>, List<R>>, Either<L, R>, Either<List<L>, List<R>>> accumulator = ( e1, e2) -> { if (e2.isLeft()) { if (e1.isLeft()) { List<L> combined = e1.leftProj.get(); combined.add(e2.leftProj.get()); return left(combined); } else { List<L> initial = new LinkedList<>(); initial.add(e2.leftProj.get()); return left(initial); } } else { if (e1.isLeft()) { return left(e1.leftProj.get()); } else { List<R> combined = e1.rightProj.get(); combined.add(e2.rightProj.get()); return right(combined); } } }; BinaryOperator<Either<List<L>, List<R>>> combiner = (e1, e2) -> { if (e1.isLeft()) { if (e2.isLeft()) { List<L> combined = e1.leftProj.get(); combined.addAll(e2.leftProj.get()); return left(combined); } else { return e1; } } else { if (e2.isLeft()) { return e2; } else { List<R> combined = e1.rightProj.get(); combined.addAll(e2.rightProj.get()); return right(combined); } } }; return eithers.reduce(zero, accumulator, combiner).bimap(l -> l.stream(), r -> r.stream()); } protected interface Projection<T> extends Iterable<T> { boolean isPresent(); -
rkrzewski revised this gist
Feb 9, 2017 . 1 changed file with 29 additions and 54 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -14,67 +14,72 @@ public abstract class Either<L, R> implements Iterable<R> { protected final Projection<L> leftProj; protected final Projection<R> rightProj; protected Either(Projection<L> leftProj, Projection<R> rightProj) { this.leftProj = leftProj; this.rightProj = rightProj; } public boolean isLeft() { return leftProj.isPresent(); } public boolean isRight() { return rightProj.isPresent(); } public Optional<R> optional() { return rightProj.optioanal(); } public Stream<R> stream() { return rightProj.stream(); } public Iterator<R> iterator() { return rightProj.iterator(); } public <U> Either<L, U> map(Function<R, U> f) { if (isLeft()) { return left(leftProj.get()); } else { return right(f.apply(rightProj.get())); } } public <LL, RR> Either<LL, RR> bimap(Function<R, RR> fr, Function<L, LL> fl) { if (isLeft()) { return left(fl.apply(leftProj.get())); } else { return right(fr.apply(rightProj.get())); } } public <U> Either<L, U> flatMap(Function<R, Either<L, U>> f) { if (isLeft()) { return left(leftProj.get()); } else { return f.apply(rightProj.get()); } } public void accept(Consumer<L> ifLeft, Consumer<R> ifRight) { if (isLeft()) { ifLeft.accept(leftProj.get()); } else { ifRight.accept(rightProj.get()); } } public Either<R, L> swap() { if (isLeft()) { return right(leftProj.get()); } else { return left(rightProj.get()); } } @@ -93,10 +98,10 @@ public static <L, R> Either<L, Stream<R>> sequence(Stream<Either<L, R>> eithers) return e1; } if (e2.isLeft()) { return left(e2.leftProj.get()); } List<R> combined = e1.rightProj.get(); combined.add(e2.rightProj.get()); return right(combined); }; BinaryOperator<Either<L, List<R>>> combiner = (e1, e2) -> { @@ -106,8 +111,8 @@ public static <L, R> Either<L, Stream<R>> sequence(Stream<Either<L, R>> eithers) if (e2.isLeft()) { return e2; } List<R> combined = e1.rightProj.get(); combined.addAll(e2.rightProj.get()); return right(combined); }; return eithers.reduce(zero, accumulator, combiner).map(l -> l.stream()); @@ -190,45 +195,15 @@ public Iterator<T> iterator() { private static class Left<LL, RR> extends Either<LL, RR> { public Left(LL value) { super(new ValueProjection<LL>(value), new EmptyProjection<RR>()); } } private static class Right<LL, RR> extends Either<LL, RR> { public Right(RR value) { super(new EmptyProjection<LL>(), new ValueProjection<RR>(value)); } } } -
rkrzewski created this gist
Feb 9, 2017 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,234 @@ package pl.caltha.commons; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.Optional; import java.util.function.BiFunction; import java.util.function.BinaryOperator; import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; public abstract class Either<L, R> implements Iterable<R> { protected abstract Projection<L> leftProj(); protected abstract Projection<R> rightProj(); public boolean isLeft() { return leftProj().isPresent(); } public boolean isRight() { return rightProj().isPresent(); } public Optional<R> optional() { return rightProj().optioanal(); } public Stream<R> stream() { return rightProj().stream(); } public Iterator<R> iterator() { return rightProj().iterator(); } public <U> Either<L, U> map(Function<R, U> f) { if (isLeft()) { return left(leftProj().get()); } else { return right(f.apply(rightProj().get())); } } public <LL, RR> Either<LL, RR> bimap(Function<R, RR> fr, Function<L, LL> fl) { if (isLeft()) { return left(fl.apply(leftProj().get())); } else { return right(fr.apply(rightProj().get())); } } public <U> Either<L, U> flatMap(Function<R, Either<L, U>> f) { if (isLeft()) { return left(leftProj().get()); } else { return f.apply(rightProj().get()); } } public void accept(Consumer<L> ifLeft, Consumer<R> ifRight) { if (isLeft()) { ifLeft.accept(leftProj().get()); } else { ifRight.accept(rightProj().get()); } } public Either<R, L> swap() { if (isLeft()) { return right(leftProj().get()); } else { return left(rightProj().get()); } } public static <L, R> Either<L, R> left(L value) { return new Left<L, R>(value); } public static <L, R> Either<L, R> right(R value) { return new Right<L, R>(value); } public static <L, R> Either<L, Stream<R>> sequence(Stream<Either<L, R>> eithers) { Either<L, List<R>> zero = right(new LinkedList<R>()); BiFunction<Either<L, List<R>>, Either<L, R>, Either<L, List<R>>> accumulator = (e1, e2) -> { if (e1.isLeft()) { return e1; } if (e2.isLeft()) { return left(e2.leftProj().get()); } List<R> combined = e1.rightProj().get(); combined.add(e2.rightProj().get()); return right(combined); }; BinaryOperator<Either<L, List<R>>> combiner = (e1, e2) -> { if (e1.isLeft()) { return e1; } if (e2.isLeft()) { return e2; } List<R> combined = e1.rightProj().get(); combined.addAll(e2.rightProj().get()); return right(combined); }; return eithers.reduce(zero, accumulator, combiner).map(l -> l.stream()); } protected interface Projection<T> extends Iterable<T> { boolean isPresent(); T get(); Optional<T> optioanal(); Stream<T> stream(); Iterator<T> iterator(); } private static class EmptyProjection<T> implements Projection<T> { @Override public boolean isPresent() { return false; } @Override public T get() { throw new NoSuchElementException("empty projection"); } @Override public Optional<T> optioanal() { return Optional.empty(); } @Override public Stream<T> stream() { return Stream.empty(); } @Override public Iterator<T> iterator() { return Collections.emptyIterator(); } } private static class ValueProjection<T> implements Projection<T> { private final T value; public ValueProjection(T value) { this.value = value; } @Override public boolean isPresent() { return true; } @Override public T get() { return value; } @Override public Optional<T> optioanal() { return Optional.of(value); } @Override public Stream<T> stream() { return Stream.of(value); } @Override public Iterator<T> iterator() { return Collections.singleton(value).iterator(); } } private static class Left<LL, RR> extends Either<LL, RR> { private final Projection<LL> leftProj; private final Projection<RR> rightProj; public Left(LL value) { this.leftProj = new ValueProjection<LL>(value); this.rightProj = new EmptyProjection<RR>(); } @Override public Projection<LL> leftProj() { return leftProj; } @Override public Projection<RR> rightProj() { return rightProj; } } private static class Right<LL, RR> extends Either<LL, RR> { private final Projection<LL> leftProj; private final Projection<RR> rightProj; public Right(RR value) { this.leftProj = new EmptyProjection<LL>(); this.rightProj = new ValueProjection<RR>(value); } @Override public Projection<LL> leftProj() { return leftProj; } @Override public Projection<RR> rightProj() { return rightProj; } } }