Skip to content

Instantly share code, notes, and snippets.

@msfroh
Created March 28, 2012 21:10
Show Gist options
  • Save msfroh/2230572 to your computer and use it in GitHub Desktop.
Save msfroh/2230572 to your computer and use it in GitHub Desktop.
Functional Programming in Java Parts 2 and 3
public abstract class Curryable<T, F> {
public abstract Function1<F, T> curry();
public F apply(T t) {
return curry().apply(t);
}
}
public abstract class Function2<R, T1, T2>
extends Curryable<T1, Function1<R,T2>> {
public abstract R apply(final T1 i1, final T2 i2);
@Override
public Function1<Function1<R, T2>, T1> curry() {
return new Function1<Function1<R, T2>, T1>() {
public Function1<R, T2> apply(final T1 i1) {
return new Function1<R, T2>() {
@Override
public R apply(final T2 i2) {
return Function2.this.apply(i1, i2);
}
};
}
};
}
}
public abstract class Function3<R, T1, T2, T3>
extends Curryable<T1, Function2<R, T2, T3>> {
public abstract R apply(final T1 i1, final T2 i2, T3 i3);
@Override
public Function1<Function2<R, T2, T3>, T1> curry() {
return new Function1<Function2<R, T2, T3>, T1>() {
public Function2<R, T2, T3> evaluate(final T1 i1) {
return new Function2<R, T2, T3>() {
@Override
public R apply(final T2 i2, final T3 i3) {
return Function3.this.apply(i1, i2, i3);
}
};
}
};
}
}
public abstract class Function2<R, T1, T2> extends Curryable<T1, Function1<R,T2>> {
public abstract R evaluate(final T1 i1, final T2 i2);
@Override
public Function1<Function1<R, T2>, T1> curry() {
return new Function1<Function1<R, T2>, T1>() {
public Function1<R, T2> evaluate(final T1 i1) {
return new Function1<R, T2>() {
@Override
public R evaluate(final T2 i2) {
return Function2.this.evaluate(i1, i2);
}
};
}
};
}
public final Function0<R> apply(final T1 i1, final T2 i2) {
return apply(i1).apply(i2);
}
}
public abstract class Function3<R, T1, T2, T3> extends Curryable<T1, Function2<R, T2, T3>>{
public abstract R evaluate(final T1 i1, final T2 i2, T3 i3);
@Override
public Function1<Function2<R, T2, T3>, T1> curry() {
return new Function1<Function2<R, T2, T3>, T1>() {
public Function2<R, T2, T3> evaluate(final T1 i1) {
return new Function2<R, T2, T3>() {
@Override
public R evaluate(final T2 i2, final T3 i3) {
return Function3.this.evaluate(i1, i2, i3);
}
};
}
};
}
public final Function0<R> apply(final T1 i1, final T2 i2, final T3 i3) {
return apply(i1).apply(i2).apply(i3);
}
}
public class MemoizationUtils {
/* ... previous definition of memoize for Function1... */
public static <R, T1, T2> MemoizedFunction2<R, T1, T2>
memoize(final Function2<R, T1, T2> f) {
return new MemoizedFunction2<R, T1, T2>() {
@Override
public R evaluate(Function2<R, T1, T2> self,
final T1 i1, final T2 i2) {
return f.evaluate(this, i1, i2);
}
};
}
public static <R,T1,T2,T3> MemoizedFunction3<R, T1, T2, T3>
memoize(final Function3<R, T1, T2, T3> f) {
return new MemoizedFunction3<R, T1, T2, T3>() {
@Override
public R evaluate(Function3<R, T1, T2, T3> self,
final T1 i1, final T2 i2, final T3 i3) {
return f.evaluate(this, i1, i2, i3);
}
};
}
}
System.out.println("4 + 5 = " + add.apply(4).apply(5));
// More explicitly, we can capture the resulting function in a variable:
final Function1 addFour = add.apply(4);
System.out.println("4 + 5 = " + addFour.apply(5));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment