Skip to content

Instantly share code, notes, and snippets.

@ezksd
Created February 28, 2017 16:01
Show Gist options
  • Save ezksd/8711a681b3d07a5ae065dc6220195e8f to your computer and use it in GitHub Desktop.
Save ezksd/8711a681b3d07a5ae065dc6220195e8f to your computer and use it in GitHub Desktop.
import java.util.function.Function;
import java.util.function.Supplier;
interface TailRec<A> {
default <B> TailRec<B> map(Function<A, B> f) {
return flatmap(x -> new Call<>(() -> new Done<>(f.apply(x))));
}
default <B> TailRec<B> flatmap(Function<A, TailRec<B>> f) {
if (this instanceof Done) {
Done<A> done = (Done<A>) this;
return new Call<B>(() -> f.apply(done.val()));
} else if (this instanceof Call) {
Call<A> call = (Call<A>) this;
return new Cont<>(call, f);
} else if (this instanceof Cont) {
Cont<Object, A> c = (Cont<Object, A>) this;
return new Cont<>(c.head(), x -> c.fun().apply(x).flatmap(f));
} else {
throw new RuntimeException("illegal state");
}
}
//
// default A result() {
// if (this instanceof Done) {
// Done<A> done = (Done<A>) this;
// return done.val();
// } else if (this instanceof Call) {
// Call<A> call = (Call<A>) this;
// return call.next().result();
// } else if (this instanceof Cont) {
// Cont<Object, A> cont = (Cont<Object, A>) this;
// TailRec<Object> head = cont.head();
// Function<Object, TailRec<A>> fun = cont.fun();
// if (head instanceof Done) {
// Done<Object> done = (Done<Object>) head;
// return fun.apply(done).result();
// } else if (head instanceof Call) {
// Call<Object> call = (Call<Object>) head;
// return call.next().flatmap(fun).result();
// } else if (head instanceof Cont) {
// Cont<Object, Object> cont1 = (Cont<Object, Object>) head;
// return cont1.head().flatmap(x -> cont1.fun().apply(x).flatmap(fun)).result();
// } else {
// throw new RuntimeException("123");
// }
// } else {
// throw new RuntimeException("123");
// }
//
// }
default A result() {
TailRec<A> t = this;
while (!(t instanceof Done)) {
if (t instanceof Call) {
Call<A> call = (Call<A>) t;
t = call.next();
} else if (t instanceof Cont) {
Cont<Object, A> cont = (Cont<Object, A>) t;
TailRec<Object> head = cont.head();
Function<Object, TailRec<A>> fun = cont.fun();
if (head instanceof Done) {
Done<Object> done = (Done<Object>) head;
t= fun.apply(done);
} else if (head instanceof Call) {
Call<Object> call = (Call<Object>) head;
t = call.next().flatmap(fun);
// return call.next().flatmap(fun).result();
} else if (head instanceof Cont) {
Cont<Object, Object> cont1 = (Cont<Object, Object>) head;
t = cont1.head().flatmap(x -> cont1.fun().apply(x).flatmap(fun));
} else {
throw new RuntimeException("123");
}
} else {
throw new RuntimeException("123");
}
}
Done<A> done = (Done<A>) t;
return done.val();
}
class Done<A> implements TailRec<A> {
A val;
Done(A val) {
this.val = val;
}
A val() {
return val;
}
}
class Call<A> implements TailRec<A> {
Supplier<TailRec<A>> sup;
Call(Supplier<TailRec<A>> sup) {
this.sup = sup;
}
TailRec<A> next() {
return sup.get();
}
}
class Cont<A, B> implements TailRec<B> {
TailRec<A> a;
Function<A, TailRec<B>> f;
Cont(TailRec<A> a, Function<A, TailRec<B>> f) {
this.a = a;
this.f = f;
}
TailRec<A> head() {
return a;
}
Function<A, TailRec<B>> fun() {
return f;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment