skip to content

What is currying in Kotlin, and how do you encode a two-argument function like add(a, b) as a curried function using returned lambdas?

level: juniorimportance: should knowfreq 35%

answer

  1. One arg at a time, each returns the next function
  2. (Int) -> (Int) -> Int is right-associative
  3. Inner lambda is a closure over the outer param
  4. add(1)(2) chains the calls
  5. No built-in curry in Kotlin — nested lambdas

basics

~20 s

Currying turns a function that takes many arguments into a chain of functions that each take one argument and return the next function. You do it in Kotlin by returning a lambda from a lambda.

solid answer

~40 s

Currying transforms an n-argument function into a sequence of single-argument functions, each returning the next. In Kotlin there is no built-in `curry` operator; you encode it manually with nested lambdas. For `add(a, b)` you write a value of type `(Int) -> (Int) -> Int`: `val add: (Int) -> (Int) -> Int = { a -> { b -> a + b } }`. Calling `add(1)` returns a `(Int) -> Int` closure that has captured `a = 1`; calling `add(1)(2)` finally yields `3`. The inner lambda is a closure over the outer parameter. Kotlin's function-type syntax `(Int) -> (Int) -> Int` is right-associative, matching the nesting. Currying is rare in idiomatic Kotlin because default arguments and overloads usually solve the same need more readably.

code

kotlin · 5 lines
kotlin
val add: (Int) -> (Int) -> Int = { a -> { b -> a + b } }

val sum = add(1)(2)   // 3
val addTen = add(10)  // (Int) -> Int closure capturing a = 10
println(addTen(5))    // 15

go deeper

for a junior

Can state that currying breaks an n-arg function into single-arg functions and write the nested-lambda form with the correct (Int) -> (Int) -> Int type.

for a middle

Explains right-associativity of -> and that the intermediate value is a closure capturing the first argument.

for a senior

Notes Kotlin has no built-in currying and that default/named arguments are the idiomatic substitute; can reason about when currying actually pays off.

for a principal

Frames currying as a building block for generic combinators/point-free pipelines and weighs its readability cost against Kotlin idioms in a shared codebase.

## What currying is **Currying** is the technique of rewriting a function that takes multiple arguments into a chain of functions that each take exactly **one** argument and return the next function in the chain, until the final one returns the result. The name comes from logician Haskell Curry. A normal two-argument function: ```kotlin fun add(a: Int, b: Int): Int = a + b ``` Its **curried** form is a function that takes `a` and returns *another function* that takes `b`: ```kotlin val add: (Int) -> (Int) -> Int = { a -> { b -> a + b } } val result = add(1)(2) // 3 val addOne = add(1) // (Int) -> Int, with a captured as 1 val three = addOne(2) // 3 ``` ## Reading the type The type `(Int) -> (Int) -> Int` means "a function from `Int` to (a function from `Int` to `Int`)". The `->` arrow is **right-associative**, so it groups as `(Int) -> ((Int) -> Int)`. That mirrors the nested lambdas exactly. ## Why it works: closures The inner lambda `{ b -> a + b }` is a **closure** — it captures the variable `a` from its enclosing scope. When you call `add(1)`, you create a new function object that remembers `a = 1`. This captured state is what makes currying useful: each application "locks in" one argument. ## How you invoke each stage - `add` is `(Int) -> (Int) -> Int` - `add(1)` returns `(Int) -> Int` - `add(1)(2)` returns `Int` You can also stop partway and store the intermediate function (`val addOne = add(1)`), which is the bridge to **partial application**. ## Idiomatic note Kotlin has **no built-in currying operator** (unlike Haskell, where every function is curried by default). You hand-roll it with nested lambdas. In practice Kotlin developers prefer **default arguments**, **named arguments**, and **overloads** for the same ergonomic goals, reserving currying for functional-style pipelines and generic combinators.

  • What is the type of add(1) before you supply the second argument?
    (Int) -> Int — a single-argument function closing over a = 1.
  • Why is the function type written (Int) -> (Int) -> Int and not ((Int) -> Int) -> Int?
    The arrow is right-associative, so it naturally means a function returning a function; the alternative would mean a function that takes a function as its argument — a different signature.

Like a vending machine that first asks for your coins, then hands you a second machine that asks which snack — one choice per step.

saying these in an interview costs you the question

  • Confusing currying with overloading or with simply calling a function twice
  • Thinking Kotlin has a built-in curry keyword/operator
  • Writing the type as ((Int) -> Int) -> Int and calling it curried
  • Not understanding that the inner lambda captures the outer argument via a closure

context