The beauty of currying
Tags: kotlin, java, functional
Published: 2022-06-08 22:52:18

---
title: The beauty of currying
published: true
description: Currying is a FP technique to create functions, let's see how it applies in a language and how can be used
tags: kotlin,java,fp
---

## What is currying?

Currying is the fine art of transforming a function with arity `n` into `n` functions with arity 1.

This means: Given a function that takes X parameters, generate X functions that take only 1 parameter.

Using the wikipedia example:

- Given `x = ƒ(a, b, c)` it becomes:
  - `h = g(a)`
  - `i = h(b)`
  - `x = i(c)`
- Or in a single sequence call: `x = g(a)(b)(c)`

The name comes from Haskell Curry, a famous mathematician who developed a lot of concepts in modern math.

## What it means in modern programming?

It simply means that you have a way to reduce the complexity of a function call creating intermediate functions which in turn return newer functions.
It will be more clear with examples...

### A taste of currying

Let's start with a _"simple function"_ it takes 2 numbers and returns the sum of them:

`sum = { a: Int, b: Int } => a + b`

Let's imagine for a second that we have a `curry` function that will give back the curried version of our function, a call of: `curry(sum)` will generate `curriedSum` which can be invoked like: `curriedSum(a)(b)` instead of the original call: `sum(a, b)`.

There's also the possibility of actually set some of its values and do **PARTIAL APPLICATION** which means setting a value for one (or more) of the parameters.

On our `sum` example:

```kotlin
val curriedSum = curry(sum) // return value is: { a -> { b -> a + b } }
// Or also expressed as: (Int) -> (Int) -> Int
val add5 = curriedSum(5) // returns: (Int) -> Int = { b -> 5 + b } 
val add7 = curriedSum(7) // returns: (Int) -> Int = { b -> 7 + b } 

add5(42) // 47
add7(13) // 20
add5(add7(10))
curriedSum(17)(7)// 24 :: add5(add7(10)) -> add5(17)
```

#### Why would I want that?

There are multiple reasons for wanting to curry a function:

- We don't have all the values that will be passed right now, we usually
  have to create callbacks or proxies or mechanism to obtain these values before actually calling a function.
- We need to pass a function as parameter to another function (callbacks) and we already have a function defined to do the work.
- We want to **partially apply** a function to pass it along to other places but keeping our data contextualized in there, sounds weird but imagine you have to pass a callback or pass a filtering function, and you already have a function that does the job, but with additional flags or parameters.
- We need a simple way to provide a complex API shared between parts at different moments.

Truth is you maybe don't need it or have other approaches that can do the work as well, still is worth the shot to understand how it works in case you need it some day.

## Let's see it in action

For this example, let's imagine we have a function that can do a POST to a web service and returns information.

```kotlin
fun <T> postCall(
    domain: String, 
    port: Int, 
    path: String, 
    queryParams: QueryParams,
): T {
    //... Here happens the magic call
}
```

Each call will be complex:

```kotlin
postCall<MovieResponse>(
  "moviedb.com", 
  8090, 
  "/movies/scott-pilgrim", 
  QueryParams(
    "order" to "asc",
    "type" to Types.JSON,
    "comments" to false
  )
)
//...
postCall<MovieResponse>(
  "moviedb.com", 
  8090,
  "/movies/lego-movie", 
  QueryParams(
    "order" to "desc",
    "type" to Types.JSON,
    "comments" to true
  )
)
//...
```

This is error-prone and can be improved:

* Using a builder:
```kotlin
  createMovieCall()
    .forMovie("lego-movie")
    .withParams("order" to "desc", "type" to Types.JSON, "comments" to true)
    .call()
```
* Using a class:
  ```kotlin
    val imdbService = MovieService(
        params = "default", 
        domain = Domains.IMDB
    )
    imdbService.getMovie("scott-pilgrim")
  ```
* Other cooler ways that are not as cool as currying.

But with currying we can do something like:

```kotlin
val movieService = curry(postCall)("moviedb.com")(8090)

val scottPilgrimCall = movieService("/movies/scott-pilgrim")
val scottPilgrimWithComments = scottPilgrimCall("comments" to true)
val scottPilgrimNoComments = scottPilgrimCall("comments" to false)

val legoMovieCall = movieService("/movies/lego-movie")
val legoMovieYAML = legoMovieCall("type" to Types.YAML)
val legoMovieXML = legoMovieCall("type" to Types.XML )
val legoMovieJSON = legoMovieCall("type" to Types.JSON)
```

This approach allow to create the intermediate calls and keep previous parameters without problems, we can even create a
"movie service generator":

```kotlin
fun movieServiceGenerator(
  movieWeb: string
): (String) -> (QueryParams) -> MovieResponse =
  curry(postCall)(movieWeb)(8090) // Assuming both sites use this port

val imdbService = movieServiceGenerator("imdb.com")
val cuevanaService = movieServiceGenerator("cuevana3.me")

// And the calls will be similar:

val jumanjiIMDB = imdbService("/movie/jumanji")(QueryParams())
val jumanjiCuevana = cuevanaService("/92345/jumanji")(QueryParams("server" to "webfree2"))
```

The syntax is different but the way we pass data evolves to return functions with partially applied data so, we can build functions with simpler calls.

## How to implement it

Depending on what your language allows with functions it can be easy or hard or even unreadable (but easy to use).

For example, in Haskell all calls with multiple parameters are _auto curried_ which means that a function:

```haskell
postcall :: String -> Int -> String -> [(String, String)] -> a
```

Is the same as:

```haskell
postcall :: String -> (Int -> (String -> ([(String, String)] -> a)))
```

So we can do partial application if needed:

```haskell
imdbservice = postcall "imdb.com" 8090

scott_pilgrim = imdbservice "/movies/scott-pilgrim"
scott_pilgrim_comments = scott_pilgrim [("comments", "true")]
```

In JS defining a currying function gets interesting:

```javascript
function curry(func) {
    return function curried(...args) {
        if (args.length >= func.length) {
            return func.apply(this, args)
        } else {
            return function (...args2) {
                return curried.apply(this, args.concat(args2))
            }
        }
    }
}
```

But there are a lot of solutions out there, like lodash:

```javascript
const curried = _.curry(postcall)
const imdbService = curried("imdb.com")(8090)
const legoMovie = imdbService("/movies/lego-movie")({})
```

Other languages can get complicated as we need to know the number of arguments for our application, like kotlin:

```kotlin
fun <A, B, R> curry(f: (A, B) -> R): (A) -> (B) -> R {
    return { a: A -> { b: B -> f(a, b) } }
}

fun <A, B, C, D, R> curry(f: (A, B, C, D) -> R): (A) -> (B) -> (C) -> (D) -> R =
    { a: A ->
        { b: B ->
            { c: C ->
                { d: D -> f(a, b, c, d) }
            }
        }
    }

fun postCall(
  web: String, 
  port: Int, 
  path: String, 
  params: Map<String, String>): MovieResponse {
    //...
}

val curried = curry(::postCall)
println(curried("imdb")(9090)("/lego")(mapOf("format" to "json")))
// And so on...
```

Depending on how much your platform (language) allows, it can be messy...

```java

@FunctionalInterface
interface TetraFunction<A, B, C, D, R> {
    R apply(A a, B b, C c, D d);
}

class Curry {
    public static <A, B, R> Function<A, Function<B, R>> curry(BiFunction<A, B, R> f) {
        return (a) -> (b) -> f.apply(a, b);
    }

    public static <A, B, C, D, R> 
    Function<A, 
            Function<B, 
                    Function<C, 
                            Function<D, R>>>> curry(TetraFunction<A, B, C, D, R> f) {
        return (a) -> (b) -> (c) -> (d) -> f.apply(a, b, c, d);
    }
}

//Usage:
class Example {
    static <T> T postCall(
            String movieWeb, 
            int port, 
            String path, 
            Map<String, String> params) {
        
    }
    
    public static void main(String[] args){
        Function<String, 
                Function<Integer, 
                        Function<String, 
                                Function<Map<String, String>, 
                                        MovieResponse>>>> curriedPostCall = Curry.curry(Example::postCall);
        
        MovieResponse movieResponse = curriedPostCall.apply("imdb.com").apply(9890).apply("/lego-movie").apply(new HashMap());
    }
}
```

The concept and application stays almost the same, only adapting it to each language/platform.

And I did not show this time a complete example as we already covered a lot, but the ideal scenario for using currying is when you have functions taking functions and returning other functions.

## Conclusions

- Functional Programming creates a lot of intermediate data
- Currying is cool if you need to simplify your function calls
- Currying is cool if you need to partially apply your functions
- Currying is not a silver bullet but can help you create a simpler API