One of the first topics you will encounter when studying functional programming will probably be currying. For an imperative programmer not used to mathematical notations, chances are you will find the concept hard to grasp. Then let this be the day you will remember as the day you completely understood currying!

There is no love sincerer than the love of food

The technique called currying is named after the logician Haskell Curry. But as you probably know, a curry is also a variety of Indian dishes. To understand the technique, let’s use the latter to clarify the former. I found a great recipe How to Make Curry at the Tast of Home website. The simplified tasks of the recipe are:

make curry

I just enjoy translating

We got the recipe, now let’s transform it to old-fashioned Java code. For the first three tasks, we will create custom classes to represent the items. This is what the Meat class looks like:

public class Meat {
  public final Duration preparationTime;

  public Meat(Duration preparationTime) {
    this.preparationTime = preparationTime;
  }

  @Override
  public String toString() {
    return "Brown the meat (" + preparationTime.toMinutes() + " minutes)";
  }
}

The Onion and Spices classes do look exactly the same, so there is no need to list them here. With these classes and the recipe, we can create a method to print the tasks. I kept the implementation quite simple:

static void createCurry(Meat m, Onion o, Spices s, Duration simmerDuration, Duration cookingDuration) {
  System.out.println("• " + m);
  System.out.println("• " + o);
  System.out.println("• " + s);
  System.out.println("• Simmer away (" + simmerDuration.toMinutes() + " minutes)");
  System.out.println("• Cook the meat (" + cookingDuration.toMinutes() + " minutes)");
  System.out.println("• Enjoy!");
}

If you want to use this function, it’s just as easy as calling it with the appropriate objects:

createCurry(
  new Meat(Duration.ofMinutes(5)),
  new Onion(Duration.ofMinutes(5)),
  new Spices(Duration.ofSeconds(30)),
  Duration.ofMinutes(5),
  Duration.ofMinutes(8)
);

Any fool can know, the point is to understand

Before we can change the imperative code, one first need to understand what currying is all about. Just by going to Wikipedia, you will be confronted by a lot of math. If you just want to understand the basics, you don’t need all that stuff.

Currying is really nothing more than changing one function with multiple arguments to multiple functions with one argument. To achieve this, the 'multiple functions' all return a new function where the next argument can be applied to.

To understand this properly, take a look at the following code. On the left side you see a function that adds two arguments, at the right you see how it is invoked:

static int add(int a, int b) {
  return a + b;
}
int three = add(1, 2);

If we want to change the function to a curried variant, which uses one argument at a time, two steps are required. First we feed the first argument, then we apply the other argument to the first. In Java this would be like:

static Function<Integer, Integer> add(int a) {
  return b -> a + b;
}
Function<Integer, Integer> f = add(1);
int three = f.apply(2);

Just by checking this code, you may wonder what’s going on here. If we follow the curried add function top to bottom, it will make sense. At first, we called the add function with an argument of 1. Then we encounter a lambda. You could translate this lambda by saying it defines a function with an integer input of b, a body of adding two integers (a and b) and an output that returns the added up integer. If we were to fill in the incoming number in the return statement, the lambda would look like return b → 1 + b. To make it clearer, we could convert the returning lambda to 'old' Java:

static int f(int b) {
  return 1 + b;
}

The caller needs to execute this function. Java provides the apply(int b) method to do this. We can just fill in our second argument, that is 2, to do the calculation. Note that the caller could do it in a one-liner, by simply writing add(1).apply(2) [1].

If you still find it difficult to understand, we could try something else by turning above explanation into a messenger chat image. After all, they say a picture says more than a thousand words:

iphone currying

I have just remembered something

Back to the curry recipe. Our implementation is a litte more complicated than a simple add function. The createCurry function does have 5 whopping arguments! To make a curried version we should return a function, that does return a function, that does return a function, that does return a function that does return a function as well…​ Wow, sounds complicated!

Actually, it is not that hard. The curry concept we just discovered works for multiple arguments exactly the same. In case you forgot, the original createCurry function has Meat, Onion, Spices and two Durations as input objects. Bearing that in mind, we need a function that has Meat as input and returns a function to calculate the rest. This rest would be a function that has Onion as input and returns a function to calculate the rest. That rest would here be a function that has Spcices as input and returns a function…​ As the list goes on, I think you could do the math!

In Java defining such a function is super verbose, but it does the job:

Function<Meat, Function<Onion, Function<Spices, Function<Duration, Function<Duration, Void>>>>>

Did you notice the Void type? It might be surprising to you. Why should it even be there? Well, our original createCurry method does not return anything, it has the void keyword. To imitate that in a functional way we just 'return' nothing; in Java we could achieve this by using java.lang.Void class[2].

Be disciplined while implementing ideas

We gained all the knowledge to implement the createCurry in a curried way. If we would create a method that returns above function, we are good to go. The implementation does look much more the same as the original function as you would expect:

static Function<Meat, Function<Onion, Function<Spices, Function<Duration, Function<Duration, Void>>>>> createCurry() {
  return m -> o -> s -> simmerDuration -> cookingDuration -> {
    System.out.println("• " + m);
    System.out.println("• " + o);
    System.out.println("• " + s);
    System.out.println("• Simmer away (" + simmerDuration.toMinutes() + " minutes)");
    System.out.println("• Cook the meat (" + cookingDuration.toMinutes() + " minutes)");
    System.out.println("• Enjoy!");
    return null;
  };
}

But I can imagine all those arrows are giving you a headache. Remember every function returns a new function (where the last function does not return a new function anymore, thus it returns null). If you can’t wrap your head around this, maybe next notation will help you out:

static Function<Meat, Function<Onion, Function<Spices, Function<Duration, Function<Duration, Void>>>>> createCurry() {
  return m -> { // Function<Meat, Function<Onion, ...>>
    return o -> { // Function<Onion, Function<Spices, ...>>
      return s -> { // Function<Spices, Function<Duration, ...>>
        return simmerDuration -> { // Function<Duration, Function<Duration, ...>>
          return cookingDuration -> { // Function<Duration, Void>
            // implementation
            return null;
          }
        };
      };
    };
  };
}

You are called to do a certain work – do it

As everything is in place, let the magic happen! Calling the curried createCurry function is a breeze:

createCurry()
  .apply(new Meat(Duration.ofMinutes(5)))
  .apply(new Onion(Duration.ofMinutes(5)))
  .apply(new Spices(Duration.ofSeconds(30)))
  .apply(Duration.ofMinutes(5))
  .apply(Duration.ofMinutes(8));

The garbage can is for things that have no importance

As you prepare your delicious curry, you start to wonder whether currying is really such a big deal. In the end the original createCurry function did achieve exactly the same of the curried version. So why would you use this technique?

Well, now is the time to reveal a little secret. I have simplified the last step, Cook the meat, a bit. Actually it is described by Taste of Home as "cook the meat for 5 to 10 minutes". If we were to divide this step in different options from five to ten minutes, there would be six function calls when we use the original function:

createCurry(new Meat(Duration.ofMinutes(5)), new Onion(Duration.ofMinutes(5)), new Spices(Duration.ofSeconds(30)), Duration.ofMinutes(5), Duration.ofMinutes(5));
createCurry(new Meat(Duration.ofMinutes(5)), new Onion(Duration.ofMinutes(5)), new Spices(Duration.ofSeconds(30)), Duration.ofMinutes(5), Duration.ofMinutes(6));
createCurry(new Meat(Duration.ofMinutes(5)), new Onion(Duration.ofMinutes(5)), new Spices(Duration.ofSeconds(30)), Duration.ofMinutes(5), Duration.ofMinutes(7));
createCurry(new Meat(Duration.ofMinutes(5)), new Onion(Duration.ofMinutes(5)), new Spices(Duration.ofSeconds(30)), Duration.ofMinutes(5), Duration.ofMinutes(8));
createCurry(new Meat(Duration.ofMinutes(5)), new Onion(Duration.ofMinutes(5)), new Spices(Duration.ofSeconds(30)), Duration.ofMinutes(5), Duration.ofMinutes(9));
createCurry(new Meat(Duration.ofMinutes(5)), new Onion(Duration.ofMinutes(5)), new Spices(Duration.ofSeconds(30)), Duration.ofMinutes(5), Duration.ofMinutes(10));

Frankly, this looks quite ugly. Besides appearance, imagine you need to change the Onion duration. Six lines of code have to be changed…​ And what if the code grows and you need to break it up into multiple components? You can’t do it easily, because everything is calculated within one function. Now consider calling the curried variant:

Function<Duration, Void> unfinishedCurry = createCurry().apply(new Meat(Duration.ofMinutes(5))).apply(new Onion(Duration.ofMinutes(5))).apply(new Spices(Duration.ofSeconds(30))).apply(Duration.ofMinutes(5));

unfinishedCurry.apply(Duration.ofMinutes(5));
unfinishedCurry.apply(Duration.ofMinutes(6));
unfinishedCurry.apply(Duration.ofMinutes(7));
unfinishedCurry.apply(Duration.ofMinutes(8));
unfinishedCurry.apply(Duration.ofMinutes(9));
unfinishedCurry.apply(Duration.ofMinutes(10));

Yep, that’s looking already a lot better. Only the last step of the recipe is called several times; therefore there is lot less code duplication. You can move the unfinishedCurry function effortless to another module[3]. And to get real bang for your bucks, you could write a for loop to finish all steps. In combination with an IntStream, it looks just perfect:

IntStream.rangeClosed(5, 10).forEach(i -> unfinishedCurry.apply(Duration.ofMinutes(i)));

All in all currying brings a lot of benefits!

Start where you are, use what you have, do what you can

Like all things concerning programming, the only way to truely understand it is by doing it yourself. The same applies to making an Indian curry by the way 😜. So go out there and try to make your own curried function. To give you a head start, the source code I used in this blog can found here. Good luck!


1. In real functional languages you can write the invocation of curried function a lot sweeter. In Scala, for instance, there is syntactic sugar to write this as add(1)(2).
2. If you are more familiar with the functional classes, you may wonder why I did not use a Consumer<Duration> instead. You would be right of course, but I choose to keep the example as clear a possible. By defining a Void, I think it easier to understand how you go from a uncurried void function to a curried variant.
3. When you think about this, it gets even more wonderful, because you can break up the function composition any time you want. For example, you could put var fun = createCurry().apply(new Meat(Duration.ofMinutes(5))) in module A and use this function in module B.
shadow-left