Skip to content

Instantly share code, notes, and snippets.

@nvanderw
Created April 13, 2013 22:25
Show Gist options
  • Save nvanderw/5380350 to your computer and use it in GitHub Desktop.
Save nvanderw/5380350 to your computer and use it in GitHub Desktop.
public class Thunks {
/**
* Interface which represents unary functions. Can be anonymously
* instantiated to simulate lambdas.
*/
public static interface Fn<A, B> {
public B call(A arg);
}
/**
* Composition f . g of unary functions. (f . g)(x) = f(g(x))
*/
public static <A, B, C> Fn<A, C> compose(final Fn<B, C> f, final Fn<A, B> g) {
return new Fn<A, C>() {
public C call(A arg) {
return f.call(g.call(arg));
}
};
}
/**
* Represents types which can be mapped over. Should satisfy the property
* that foo.map(f).map(g) = foo.map(compose(g, f)).
*/
public static interface Functor<A> {
public <B> Functor<B> map(Fn<A, B> fn);
}
/**
* Represents a lazy value that can be computed when needed.
* The functor implementation creates a new thunk which, when forced,
* forces the original and applies the given function.
*/
public static abstract class Thunk<T> implements Functor<T> {
public abstract T force();
private Thunk<T> outer = this;
public <V> Thunk<V> map(final Fn<T, V> fn) {
return new Thunk<V>() {
public V force() {
return fn.call(outer.force());
}
};
}
}
public static void main(String[] args) {
final Thunk<Integer> thunk = new Thunk<Integer>() {
public Integer force() {
System.out.println("Thunk evaled");
return 2;
}
};
final Thunk<Integer> twice = thunk.map(new Fn<Integer, Integer>() {
public Integer call(Integer arg) {
return 2 * arg;
}
});
System.out.printf("%d\n", twice.force());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment