Real-world currying

March 09, 2016

This is from a response to a thread in /r/functionalprogramming.

The most common case of real-world currying I run into is applicative validation of functions of mulitple arguments.

To be able to use ap and map on a function of type (A, B) => C, I have to convert it to a function of type A => B => C, e.g. using .curried in Scala.

Here's an example (using Scalaz's Validation for brevity) where I have to curry the binary mult function:

import scalaz._
import Scalaz._

def parse(x: String): Validation[List[String],Int] =
  try {
    Success(x.toInt)
  } catch {
    case e: NumberFormatException =>
      Failure(List(s"couldn't parse ${x}"))
  }

def mult(x: Int, y: Int): Int = { x * y }

def x: Validation[List[String], Int] =
  parse("6").ap(parse("7").map((mult _).curried))

def y: Validation[List[String], Int] =
  parse("six").ap(parse("seven").map((mult _).curried))

println(x) // Success(42)
println(y) // Failure(List(couldn't parse seven, couldn't parse six))

This article is literate Scala:

/***
libraryDependencies += "org.scalaz" %% "scalaz-core" % "7.1.0"
*/
$ curl -sL earldouglas.com/posts/real-world-currying.md | codedown scala > real-world-currying.scala
$ sbt -Dsbt.main.class=sbt.ScriptMain real-world-currying.scala
Success(42)
Failure(List(couldn't parse seven, couldn't parse six))