scalabeginner

Currying and Partial Application

Use currying and partial application for function composition and reusable logic.

scala
// Curried function
def add(a: Int)(b: Int): Int = a + b

// Partial application
val add5 = add(5)  // Int => Int
val add10 = add(10)

// Multiple parameter lists
def configure(host: String)(port: Int)(debug: Boolean): String =
  s"$host:$port (debug=$debug)"

val devConfig = configure("localhost")(8080)
val devDebug = devConfig(true)
val devProd = devConfig(false)

// Convert regular function to curried
def multiply(a: Int, b: Int): Int = a * b
val curriedMul = (multiply _).curried
val double = curriedMul(2)
val triple = curriedMul(3)

// Currying for type inference
def transform[A, B](items: List[A])(f: A => B): List[B] =
  items.map(f)

// With context parameters
def withLogging[A](label: String)(action: => A): A =
  println(s"  [$label] Starting...")
  val result = action
  println(s"  [$label] Done: $result")
  result

// Fold as curried
def foldLeft[A, B](init: B)(items: List[A])(f: (B, A) => B): B =
  items.foldLeft(init)(f)

val sum = foldLeft(0)(_: List[Int])(_ + _)
val product = foldLeft(1)(_: List[Int])(_ * _)

// Builder pattern with currying
def request(method: String)(url: String)(headers: Map[String, String])(body: String): String =
  s"$method $url\nHeaders: $headers\nBody: $body"

val getRequest = request("GET")
val postRequest = request("POST")
val apiGet = getRequest("https://api.example.com")

@main def run(): Unit =
  println(s"add5(3) = ${add5(3)}")
  println(s"add10(7) = ${add10(7)}")
  println(s"double(21) = ${double(21)}")
  println(s"triple(14) = ${triple(14)}")

  println(s"\nDev debug: $devDebug")
  println(s"Dev prod: $devProd")

  // Type inference works well with currying
  val lengths = transform(List("hello", "world", "foo"))(_.length)
  println(s"\nLengths: $lengths")

  val uppers = transform(List("a", "b", "c"))(_.toUpperCase)
  println(s"Uppers: $uppers")

  // Logging
  println()
  withLogging("calc") { 2 + 2 }

  // Fold
  val nums = List(1, 2, 3, 4, 5)
  println(s"\nSum: ${sum(nums)}")
  println(s"Product: ${product(nums)}")

  // API request
  val resp = apiGet(Map("Accept" -> "application/json"))("")
  println(s"\n$resp")

Use Cases

  • Creating reusable function templates
  • Configuration with partial application
  • Better type inference in APIs

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.