Skip to main content

Thinking Currying !!!

Currying is a mathematical concept based on lambda calculus. It is a technique of operating on a function (taking multiple arguments) by splitting and capable of chaining into a series of single argument functions. It is very similar to what a human would attempt to do on paper. For example, if you have to add numbers 1 through 10, what would you do? Class II mathematics....zero in hand, one in the mind, add 0 and 1, so 1 in the mind, then 2 in the hand, ...up to 10. So we compute the addition with one argument at a time.

In the programming world, it is realized by transforming a n-arguments function into a (n-1) arguments function, which takes the remaining one argument. This transformation when applied recursively on each of the single argument functions is the chaining of single argument functions that I discussed earlier. Needless to say, currying is a gift of the functional programming world. In simple words, functional programming is about building functions from other functions, and so functions are treated as first class citizens (like data).

If currying is just transforming a n arguments function into a single argument function, then extension method too is an example of currying.

public static bool Replace<T>(this IList<T> srcList, int position, T item) 
{ 
   // Imagine an implementation here.... 
}

So you would be using the Replace<T> above without explicitly passing the source list to the method; one argument less.

list.Replace(2, newItem);
// instead of Replace(ilistObj, 2, newItem) if extension method was not invented.

Isn't that right? Yes, but that is not the currying from the conventional standpoint of functional programming.

For samples, we will not use the devil (any functional programming language) itself; instead we will use C#, which provides functional programming facilities. Alright, let us curry.

int Add(int x, int y) 
{ 
   return x + y; 
} 

Or to be 'functional', we may (re)write: Func<int, int, int> adderFunc = (x, y) => x + y;

To curry out an increment function, we would write as follows:-

Func<int, Func<int, int>> Incrementer() 
{ 
   return num => Add(num, 1); 
} 

and we use it is as follows:-

var inc = Incrementer(); 
Console.WriteLine(inc(5)); 
Console.WriteLine(inc(12)); 

Is that not better and wise than writing Sum(5, 1)?

If currying is just transforming a n-arguments function into a single argument function, then we should be able to write a generic currying function.

Func<T1, Func<T2, TResult>> Curry<T1, T2, TResult>(Func<T1, T2, TResult> fn) 
{ 
   return x => y => fn(x, y); 
} 

Func<int, Func<int, int>> Adder = Curry(Add); 
var Incrementor = Adder(1); 
var i = Incrementor(5); 

when we may not have actually  encountered a compelling situations to use this in the past

But isn’t this all cryptic? So why would we want to do all such cryptic things when we have not encountered any such situation....in the past? Actually we have.

When simple principles are tough for us to understand, it is our grandma who helps us. Our grandma here is C++; although grandma called it binding.

In C++, many STL algorithms require a functor (roughly equivalent to a function definition) with one argument, where as the desired function was a two or more arguments function. Then we use std::bind1st or std::bind2nd to curry it into unary function.

For instance, the count_if algorithm calculates the number of elements in a sequence that satisfy the predicate, which happens to be a unary function. Suppose we want to count the even numbers in a collection of whole numbers (and imagine this to be a tough calculation). If there was a function that could take a number and return true if it was an even number, it could be fed to count_if. But what if we had a function like the one below - a two argument function.

bool IsDivisible(int number, int divisor)
{
   return number % divisor == 0;
}

The functor we need is nothing but an IsDivisible function with the second argument as 2. We could write an IsEven function which in turn calls IsDivisible. But that could be tedious one we were write such wrappers for a function with 10 arguments. In situations like this, we curry. In C++, we (use) bind.

std::bind1st - A helper template function that creates an adaptor to convert a binary function object into a unary function object by binding the first argument of the binary function to a specified value.
std::bind2nd - A helper template function that creates an adaptor to convert a binary function object into a unary function object by binding the second argument of the binary function to a specified value.

So in our case, we will be using bind2nd, as follows:-

std::vector<int> wholeNumbers =  {
   1, 2, 4, 5, 6, 7, 9, 10, 12, 15, 17, 20
};

std::count_if(wholeNumbers.begin(),
   wholeNumbers.end(),
   std::bind2nd(IsDivisible, 2));

Unfortunately, C++ stayed with bind1st and bind2nd, and currying was not that evident or securely possible since C++ did not have required facilities, say something like delegates. So the concept has been in vogue from long time ago. Like every paradigm in programming, functional programming requires (re)aligning our thought (process). Instead of treating functions as just reusable pieces of code (as considered in procedural programming), they have to conceived as the input processors, which may return either data or whole new function; shrinked?

So that is a quick thought on Currying. I will try to share a few other thoughts related to currying, slightly expanding to functional programming but later.

Comments

Senthil said…
Nice.

I think currying truly shines in real functional languages, where the syntax hides the additional indirection. F# will let you write
let inc = add 1

for instance.
Unknown said…
Yes, you are right. Functional languages have the syntax for currying, tail recursion and lot of other things baked into them. C++ should have done that and a lot more...

Hey, wanted to discuss something with you. Will call or email you.

Popular posts from this blog

Extension Methods - A Polished C++ Feature !!!

Extension Method is an excellent feature in C# 3.0. It is a mechanism by which new methods can be exposed from an existing type (interface or class) without directly adding the method to the type. Why do we need extension methods anyway ? Ok, that is the big story of lamba and LINQ. But from a conceptual standpoint, the extension methods establish a mechanism to extend the public interface of a type. The compiler is smart enough to make the method a part of the public interface of the type. Yeah, that is what it does, and the intellisense is very cool in making us believe that. It is cleaner and easier (for the library developers and for us programmers even) to add extra functionality (methods) not provided in the type. That is the intent. And we know that was exercised extravagantly in LINQ. The IEnumerable was extended with a whole lot set of methods to aid the LINQ design. Remember the Where, Select etc methods on IEnumerable. An example code snippet is worth a thousand ...

Implementing COM OutOfProc Servers in C# .NET !!!

Had to implement our COM OOP Server project in .NET, and I found this solution from the internet after a great deal of search, but unfortunately the whole idea was ruled out, and we wrapped it as a .NET assembly. This is worth knowing. Step 1: Implement IClassFactory in a class in .NET. Use the following definition for IClassFactory. namespace COM { static class Guids { public const string IClassFactory = "00000001-0000-0000-C000-000000000046"; public const string IUnknown = "00000000-0000-0000-C000-000000000046"; } /// /// IClassFactory declaration /// [ComImport(), InterfaceType(ComInterfaceType.InterfaceIsIUnknown), Guid(COM.Guids.IClassFactory)] internal interface IClassFactory { [PreserveSig] int CreateInstance(IntPtr pUnkOuter, ref Guid riid, out IntPtr ppvObject); [PreserveSig] int LockServer(bool fLock); } } Step 2: [DllImport("ole32.dll")] private static extern int CoR...

Passing CComPtr By Value !!!

This is about a killer bug identified by our chief software engineer in our software. What was devised for ease of use and write smart code ended up in this killer defect due to improper perception. Ok, let us go! CComPtr is a template class in ATL designed to wrap the discrete functionality of COM object management - AddRef and Release. Technically it is a smart pointer for a COM object. void SomeMethod() { CComPtr siPtr; HRESULT hr = siPtr.CoCreateInstance(CLSID_SomeComponent); siPtr->MethodOne(20, L"Hello"); } Without CComPtr, the code wouldn't be as elegant as above. The code would be spilled with AddRef and Release. Besides, writing code to Release after use under any circumstance is either hard or ugly. CComPtr automatically takes care of releasing in its destructor just like std::auto_ptr . As a C++ programmer, we must be able to appreciate the inevitability of the destructor and its immense use in writing smart code. However there is a difference...