Skip to content

Instantly share code, notes, and snippets.

@aryairani
Forked from anonymous/Operation.java
Last active June 19, 2016 05:19
Show Gist options
  • Save aryairani/409649d74f16c82a0a4e3445d26e7eb1 to your computer and use it in GitHub Desktop.
Save aryairani/409649d74f16c82a0a4e3445d26e7eb1 to your computer and use it in GitHub Desktop.
package org.gtri.arfam.acs.interpreter;
import fj.F;
import fj.F2;
import fj.data.List;
public interface Operation<A> {
interface Free<A> {
class Return<B> implements Free<B> {
private final B b;
public Return(B b) {
this.b = b;
}
public <C> Free<C> flatMap(F<B, Free<C>> f) {
return f.f(b);
}
}
class Bind<A, B> implements Free<B> {
private final Operation<A> operation;
private final F<A, Free<B>> fInner;
private Bind(Operation<A> operation, F<A, Free<B>> fInner) {
this.operation = operation;
this.fInner = fInner;
}
public <C> Free<C> flatMap(F<B, Free<C>> f) {
return new Bind<>(operation, a -> fInner.f(a).flatMap(f));
}
}
<B> Free<B> flatMap(F<A, Free<B>> f);
default <B> Free<B> map(F<A, B> f) {
return flatMap(a -> new Return<>(f.f(a)));
}
static <A> Free<A> pure(A a) {
return new Return(a);
}
static <A,B> F<Free<A>, Free<B>> lift(F<A, B> f) {
return fa -> fa.map(f);
}
static <A,B,C> F2<Free<A>, Free<B>, Free<C>> lift2(F2<A, B, C> f) {
return (fa, fb) -> fa.flatMap(a -> fb.map(b -> f.f(a,b)));
}
}
class FreeOperation {
public static <B> Free<List<B>> sequence(List<Free<B>> listFreeB) {
F2<B,List<B>,List<B>> cons = List::cons; // grumble grumble java type inference
F2<Free<B>, Free<List<B>>, Free<List<B>>> folder = Free.lift2(cons)::f;
return listFreeB.foldRight(folder, Free.pure(List.nil()));
}
}
default Free<A> free() {
return new Free.Bind<>(this, Free.Return::new);
}
}
default Free<A> free() {
return new Free.Bind<>(this, Free.Return::new);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment