using System; static class YCombinator { interface Function { R apply(T t); } interface RecursiveFunction : Function, F> { } static class Y { class __1 : RecursiveFunction> { class __2 : Function { readonly RecursiveFunction> w; public __2(RecursiveFunction> w) { this.w = w; } public B apply(A x) { return w.apply(w).apply(x); } } Function, Function> f; public __1(Function, Function> f) { this.f = f; } public Function apply(RecursiveFunction> w) { return f.apply(new __2(w)); } } public static Function _(Function, Function> f) { var r = new __1(f); return r.apply(r); } } class __1 : Function, Function> { class __2 : Function { readonly Function f; public __2(Function f) { this.f = f; } public int apply(int n) { return (n <= 2) ? 1 : (f.apply(n - 1) + f.apply(n - 2)); } } public Function apply(Function f) { return new __2(f); } } class __2 : Function, Function> { class __3 : Function { readonly Function f; public __3(Function f) { this.f = f; } public int apply(int n) { return (n <= 1) ? 1 : (n * f.apply(n - 1)); } } public Function apply(Function f) { return new __3(f); } } static void Main(params String[] arguments) { Function fib = Y._(new __1()); Function fac = Y._(new __2()); Console.WriteLine("fib(10) = " + fib.apply(10)); Console.WriteLine("fac(10) = " + fac.apply(10)); } }