Last active
August 29, 2015 14:20
-
-
Save jnape/785e614867dbd2b0d5d1 to your computer and use it in GitHub Desktop.
Continuation-like iterable type
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
package com.jnape.palatable.lambda.applicative; | |
import com.jnape.palatable.lambda.functions.MonadicFunction; | |
import static com.jnape.palatable.lambda.functions.builtin.monadic.Identity.id; | |
@FunctionalInterface | |
public interface BiFunctor<A, B> { | |
default <C> BiFunctor<C, B> biMapL(MonadicFunction<? super A, ? extends C> fn) { | |
return biMap(fn, id()); | |
} | |
default <C> BiFunctor<A, C> biMapR(MonadicFunction<? super B, ? extends C> fn) { | |
return biMap(id(), fn); | |
} | |
<C, D> BiFunctor<C, D> biMap(MonadicFunction<? super A, ? extends C> f1, | |
MonadicFunction<? super B, ? extends D> f2); | |
} |
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
package com.jnape.palatable.lambda.continuation; | |
import com.jnape.palatable.lambda.applicative.Functor; | |
import com.jnape.palatable.lambda.functions.MonadicFunction; | |
import com.jnape.palatable.lambda.tuples.Tuple2; | |
import java.util.Iterator; | |
import java.util.Optional; | |
import static com.jnape.palatable.lambda.continuation.Memo.memoize; | |
import static com.jnape.palatable.lambda.tuples.Tuple2.tuple; | |
@FunctionalInterface | |
public interface Continuation<A> extends Functor<A>, Iterable<A> { | |
Optional<Tuple2<A, Continuation<A>>> next(); | |
default Continuation<A> then(Continuation<A> more) { | |
return () -> next() | |
.map(t -> Optional.of(tuple(t._1, t._2.then(more)))) | |
.orElseGet(more::next); | |
} | |
default <B> Continuation<B> remap( | |
MonadicFunction<Tuple2<A, Continuation<A>>, Optional<Tuple2<B, Continuation<B>>>> fn) { | |
return () -> next().flatMap(fn::apply); | |
} | |
default Continuation<A> memoized() { | |
class Memoized<X> implements Continuation<X> { | |
private final Memo<Optional<Tuple2<X, Continuation<X>>>> memoizedContinuation; | |
private Memoized(Continuation<X> continuation) { | |
memoizedContinuation = memoize(() -> continuation.next().map(t -> tuple(t._1, t._2.memoized()))); | |
} | |
@Override | |
public Optional<Tuple2<X, Continuation<X>>> next() { | |
return memoizedContinuation.get(); | |
} | |
} | |
return this instanceof Memoized ? this : new Memoized<>(this); | |
} | |
@Override | |
default <B> Continuation<B> fmap(MonadicFunction<? super A, ? extends B> fn) { | |
return () -> next().map(t -> t.biMap(fn, as -> as.fmap(fn))); | |
} | |
default boolean isEmpty() { | |
return next().isPresent(); | |
} | |
@Override | |
default Iterator<A> iterator() { | |
return ContinuationIterator.wrap(this); | |
} | |
} |
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
package com.jnape.palatable.lambda.continuation; | |
import java.util.Iterator; | |
import java.util.stream.Stream; | |
import static java.util.Arrays.asList; | |
public final class Continuations { | |
private Continuations() { | |
} | |
@SafeVarargs | |
public static <A> Continuation<A> continuing(A... as) { | |
return continuing(asList(as)); | |
} | |
public static <A> Continuation<A> continuing(Stream<A> as) { | |
return continuing(as.iterator()); | |
} | |
public static <A> Continuation<A> continuing(Iterable<A> as) { | |
return as instanceof Continuation ? (Continuation<A>) as : continuing(as.iterator()); | |
} | |
public static <A> Continuation<A> continuing(Iterator<A> as) { | |
return new IteratorWrappingContinuation<>(as); | |
} | |
public static String toString(Continuation continuation) { | |
StringBuilder sb = new StringBuilder("{"); | |
for (Object element : continuation) { | |
sb.append(element instanceof Continuation ? Continuations.toString((Continuation) element) : element).append(", "); | |
} | |
return sb.delete(sb.length() - 2, sb.length()).append("}").toString(); | |
} | |
} |
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
package com.jnape.palatable.lambda.functions; | |
import com.jnape.palatable.lambda.applicative.ProFunctor; | |
import com.jnape.palatable.lambda.tuples.Tuple2; | |
@FunctionalInterface | |
public interface DyadicFunction<A, B, C> extends MonadicFunction<A, MonadicFunction<B, C>>, ProFunctor<B, C> { | |
C apply(A a, B b); | |
@Override | |
default MonadicFunction<B, C> apply(A a) { | |
return (b) -> apply(a, b); | |
} | |
@Override | |
default <C1> DyadicFunction<A, C1, C> diMapL(MonadicFunction<? super C1, ? extends B> fn) { | |
return (DyadicFunction<A, C1, C>) ProFunctor.super.diMapL(fn); | |
} | |
@Override | |
default <C1> DyadicFunction<A, B, C1> diMapR(MonadicFunction<? super C, ? extends C1> fn) { | |
return (DyadicFunction<A, B, C1>) ProFunctor.super.diMapR(fn); | |
} | |
@Override | |
default <D, E> DyadicFunction<A, D, E> diMap(MonadicFunction<? super D, ? extends B> f1, | |
MonadicFunction<? super C, ? extends E> f2) { | |
return (a, d) -> f2.apply(apply(a, f1.apply(d))); | |
} | |
default DyadicFunction<B, A, C> flip() { | |
return (b, a) -> apply(a, b); | |
} | |
default MonadicFunction<Tuple2<A, B>, C> uncurry() { | |
return (ab) -> apply(ab._1, ab._2); | |
} | |
} |
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
package com.jnape.palatable.lambda.applicative; | |
import com.jnape.palatable.lambda.functions.MonadicFunction; | |
@FunctionalInterface | |
public interface Functor<A> { | |
<B> Functor<B> fmap(MonadicFunction<? super A, ? extends B> fn); | |
} |
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
package com.jnape.palatable.lambda.functions; | |
import com.jnape.palatable.lambda.applicative.Functor; | |
@FunctionalInterface | |
public interface MonadicFunction<A, B> extends Functor<B> { | |
B apply(A a); | |
@Override | |
default <C> MonadicFunction<A, C> fmap(MonadicFunction<? super B, ? extends C> f) { | |
return a -> f.apply(apply(a)); | |
} | |
default <C> MonadicFunction<A, C> then(MonadicFunction<? super B, ? extends C> f) { | |
return fmap(f); | |
} | |
default <Z> MonadicFunction<Z, B> compose(MonadicFunction<? super Z, ? extends A> g) { | |
return z -> apply(g.apply(z)); | |
} | |
} |
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
package com.jnape.palatable.lambda.applicative; | |
import com.jnape.palatable.lambda.functions.MonadicFunction; | |
import static com.jnape.palatable.lambda.functions.builtin.monadic.Identity.id; | |
@FunctionalInterface | |
public interface ProFunctor<A, B> { | |
default <C> ProFunctor<C, B> diMapL(MonadicFunction<? super C, ? extends A> fn) { | |
return diMap(fn, id()); | |
} | |
default <C> ProFunctor<A, C> diMapR(MonadicFunction<? super B, ? extends C> fn) { | |
return diMap(id(), fn); | |
} | |
<C, D> ProFunctor<C, D> diMap(MonadicFunction<? super C, ? extends A> f1, | |
MonadicFunction<? super B, ? extends D> f2); | |
} |
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
package com.jnape.palatable.lambda.tuples; | |
import com.jnape.palatable.lambda.applicative.BiFunctor; | |
import com.jnape.palatable.lambda.applicative.Functor; | |
import com.jnape.palatable.lambda.functions.MonadicFunction; | |
import static java.lang.String.format; | |
public class Tuple2<_1, _2> implements Functor<_2>, BiFunctor<_1, _2> { | |
public final _1 _1; | |
public final _2 _2; | |
public Tuple2(_1 _1, _2 _2) { | |
this._1 = _1; | |
this._2 = _2; | |
} | |
@Override | |
public final <__2> Tuple2<_1, __2> fmap(MonadicFunction<? super _2, ? extends __2> fn) { | |
return biMapR(fn); | |
} | |
@Override | |
public final <C, D> Tuple2<C, D> biMap(MonadicFunction<? super _1, ? extends C> f1, | |
MonadicFunction<? super _2, ? extends D> f2) { | |
return tuple(f1.apply(_1), f2.apply(_2)); | |
} | |
@Override | |
public final <C> Tuple2<C, _2> biMapL(MonadicFunction<? super _1, ? extends C> fn) { | |
return (Tuple2<C, _2>) BiFunctor.super.biMapL(fn); | |
} | |
@Override | |
public final <C> Tuple2<_1, C> biMapR(MonadicFunction<? super _2, ? extends C> fn) { | |
return (Tuple2<_1, C>) BiFunctor.super.biMapR(fn); | |
} | |
@Override | |
public String toString() { | |
return format("(%s, %s)", _1, _2); | |
} | |
@Override | |
public boolean equals(Object other) { | |
if (other instanceof Tuple2) { | |
Tuple2 that = (Tuple2) other; | |
return this._1.equals(that._1) && this._2.equals(that._2); | |
} | |
return false; | |
} | |
@Override | |
public int hashCode() { | |
int result = _1.hashCode(); | |
return 31 * result + _2.hashCode(); | |
} | |
public static <_1, _2> Tuple2<_1, _2> tuple(_1 _1, _2 _2) { | |
return new Tuple2<>(_1, _2); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
remap
makes things particularly interesting as a mechanism by which to lazily transform (in some cases, radically) the result of a continuation. Even complex folds can be implemented easily in terms of a remap.Examples: