A while ago I did a post about Lambda calculus in C#, mainly focusing on how you can implement the concept of Y combinators. Y combinators are one of the simplest fixed point combinators in Lambda calculus, and was discovered by a Mr Curry. One of the other interesting concepts of Lambda calculus is the concept of ‘Currying’.
Heres a quick foray back at Y Combinator:
/// /// One-argument Y-Combinator. /// public static Func<T, TResult> Y<T, TResult>(Func<Func<T, TResult>, Func<T, TResult>> F) { return t => F(Y(F))(t); } /// /// Two-argument Y-Combinator. /// public static Func<T1, T2, TResult> Y<T1, T2, TResult>(Func<Func<T1, T2, TResult>, Func<T1, T2, TResult>> F) { return (t1, t2) => F(Y(F))(t1, t2); } /// /// Three-arugument Y-Combinator. /// public static Func<T1, T2, T3, TResult> Y<T1, T2, T3, TResult>(Func<Func<T1, T2, T3, TResult>, Func<T1, T2, T3, TResult>> F) { return (t1, t2, t3) => F(Y(F))(t1, t2, t3); } /// /// Four-arugument Y-Combinator. /// public static Func<T1, T2, T3, T4, TResult> Y<T1, T2, T3, T4, TResult>(Func<Func<T1, T2, T3, T4, TResult>, Func<T1, T2, T3, T4, TResult>> F) { return (t1, t2, t3, t4) => F(Y(F))(t1, t2, t3, t4); }
Currying is the concept of integrating an argument of a function into a new function with the argument built in.
Take the following maths equation:
f(a, b, c) where f = a + b + c
so
f(1, 2, 3) would mean f = 6
The concept of currying takes the argument and effectively hardcoding it, so take a look again at the previous function.
Currying f(1, b, c) would produce a new function f1(b, c) where f1 = 1 + b + c
This idea is important of things like constructors or overloading functions, where some arguments may be fixed.
Currying in C# lambda calculus looks like the following:
// Curry first argument public static Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> F) { return t1 => t2 => F(t1, t2); } // Curry second argument. public static Func<T2, Func<T1, TResult>> Curry2nd<T1, T2, TResult>(Func<T1, T2, TResult> F) { return t2 => t1 => F(t1, t2); } // Uncurry first argument. public static Func<T1, T2, TResult> Uncurry<T1, T2, TResult>(Func<T1, Func<T2, TResult>> F) { return (t1, t2) => F(t1)(t2); } // Uncurry second argument. public static Func<T1, T2, TResult> Uncurry2nd<T1, T2, TResult>(Func<T2, Func<T1, TResult>> F) { return (t1, t2) => F(t2)(t1); }