... until the collector arrives ...

This "blog" is really just a scratchpad of mine. There is not much of general interest here. Most of the content is scribbled down "live" as I discover things I want to remember. I rarely go back to correct mistakes in older entries. You have been warned :)

2012-02-11

Java vs. Y-Combinator

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)

Blog Archive