Tonight, on You Did What?...
The gang decides to do penance for inflicting their software upon the world.
Someone suggests implementing the Y-combinator in Java. Hilarity ensues.
Rated PG for violence to a coarse language.
public final class YCombinator {
private interface Function<IN, OUT> {
OUT apply(IN x);
}
private static final Function<Function<Function<Long, Long>, Function<Long, Long>>, Function<Long, Long>> Y = new Function<Function<Function<Long, Long>, Function<Long, Long>>, Function<Long, Long>>() {
public Function<Long, Long> apply(final Function<Function<Long, Long>, Function<Long, Long>> f) {
Function g = new Function<Function<Function, Function>, Function<Long, Long>>() {
public Function<Long, Long> apply(final Function<Function, Function> h) {
return new Function<Long, Long>() {
@Override
public Long apply(Long n) {
return f.apply(h.apply(h)).apply(n);
}
};
}
};
return (Function) g.apply(g);
}
};
public static void main(String[] arguments) {
Function<Function<Long, Long>, Function<Long, Long>> fac = new Function<Function<Long, Long>, Function<Long, Long>>() {
public Function<Long, Long> apply(final Function<Long, Long> r) {
return new Function<Long, Long>() {
@Override
public Long apply(Long n) {
return n < 2 ? 1 : n * r.apply(n - 1);
}
};
}
};
System.out.println(Y.apply(fac).apply(10L));
}
}
Is this an argument for late-binding? Not necessarily: Haskell seems to cope, and you don't have to subvert the type system (much):
newtype Hold a = Hold (Hold a -> (a -> a))
y f = fg (Hold fg)
where fg hg@(Hold g) = f (g hg)