What's up with currying?

If you’ve been exposed to functional programming, you have almost certainly come across the concept of curried functions. Named after the man himself,Haskell B. Curry, a curried function is one that requires multiple arguments but cannot accept all of them in a single call. Consider the following example:

What is happening here? magnitudeis rather straightforward in that we take three values and calculate the root of the sum of their squares.magnitude_curried, however, is quite a bit different and the syntax used to declare it is perhaps a bit offputting. Here is the same function as full function expressions:If we walk through what occurs withmagnitude_curried, we’ll find that it, too, is straightforward, albeit somewhat strange (at first). When we apply the first argumentx, as1, we get back a function. Same thing when we apply the second argument,yas28. Finally, when we apply the final argument,z, as76, the magnitude function is called and its result is returned.

Where does currying come from?

Currying is a concept pulled out of the mathematical basis of functional programming, the lambda calculus. In mathematics, you cannot just go out and grab some value from the world at large and drop it in the middle of your functions. You must specify these outside values as parameters and pass them into your functions. The lambda calculus, as a formal system of arranging functions and how they are used, places additional restrictions on how your function can interact with outside information. In the lambda calculus, functions can have only a single input. In pure-functional programming languages like Haskell, every function is understood to be a curried function.

Why would we ever need currying?

You need currying when you need a function to be:

  1. Reusable
  2. Minimally dependent on context
  3. Callable after specifying some arguments

What do I mean by this? Consider how these three points apply to the following example:

Here we see thevaluesfunction being declared as a curried function. It takes an array of strings which represent keys of an object, and an actual object, and returns the values corresponding to the given keys from the provided object. In its most simple form, values could be called like so:values(['a'])({ a: 'hello' })and it would return['hello']. So how is this useful to us? On line number 8, we apply an array of strings to values and assign the resulting function to a variable calledgetNameAndDepartment. As we see on line number 9, this new variable is a fully-callable function. We pass in the first value in thecoursesarray and as expected, we get back thenameanddepartmentvalues from this object. Here comes the cool part. SincegetNameAndDepartmentis a callable function and has some of the body pre-filled, we can map over the entire courses array and use thegetNameAndDepartment

function as seen on line 12.

Big deal. This still seems like a complicated way to get the values of some objects, right? Consider the fact that thevaluesfunction doesn’t know about any particular array or object. It doesn’t describe the context, it only describes functionality. This satisfies requirement number 2 for me. Additionally, since it remained a callable function after applying the keys which we eventually map over, it satisfies number 3 as well.

This all seems fine, but what about requirement number 1: reusability? Since thevaluesfunction doesn’t describe the context, it is automatically reusable for another set of arguments. That is, we can pass in another set of values forkeysandobjand it will work there, too! We see this on line number 26 where we apply thecarKeysarray and on line number 27 where we pass in a cars object and get back themake,style, andidvalues as expected. Just as before, we can usegetMakeStyleAndId, a partially-applied function, to map over an array of car objects and get these values for each object in thecarsarray.

Currying vs partial application

There seems to be some confusion regarding the difference between currying and another similar concept called partial application. This confusion is further compounded by the fact that sometimes they are the same thing. Currying takes a function which requiresnarguments and reduces it to a series of functions which accept1argument, whereas partial application takes a function which requiresnarguments and reduces it to a function which acceptsn - 1arguments. Semantically speaking, currying is aform of partial application. In fact, in the case of a function which only needs two arguments, to begin with, these definitions are the same. This is the case for ourvaluesfunction above. We are_partially applying_the required arguments, but since the function only ever accepts one argument at a time, it is also a curried function.

Is there more insidious terminology hidden in functional programming that I should be aware of?

I recommend taking a look at thefunctional programming jargon repofromhemanthfor a huge list of well-defined FP terms. If you’re feeling daring, thefantasy-land specprovides the formal definitions of algebraic JavaScript and is what I consider to be reference material for FP in JavaScript.

Parting notes

I want to stress that the three requirements I listed are sort of the rule of thumb that I use to determine if a function needs to be curried or if I should just leave it alone. Since currying is a concept that many people are unfamiliar with, using curried functions where it doesn’t make any sense to do so is a sure-fire way to increase the probability of bugs down the road and stands to alienate newer devs and people who just don’t care for FP. If you’rejust currying because it kinda looks cool, you are obfuscating the meaning of your code.

What do you think? Are these sound guidelines? Does this help you understand the concept?

Source: http://johnnyreina.com/programming/functional/2017/09/21/whats-up-with-currying.html