Currying (named after the mathematician Haskell Curry, who discovered the technique) is a design pattern that is natural to use in F#.
To be able to use the power of currying we need to have a function that takes two or more arguments, and that the function is in the curried form.
The form can come in two shapes, curried or tupled. In F# the functions are usually in the curried form by default.
// Curried form
let add x y = x + y
// val add: x: int -> y: int -> int
// Tupled form
let add (x, y) = x + y
// val add: x: int * y: int -> int
The first example is the more idiomatic way to define functions in F#. The thing is that functions are able to return functions, so in the curried form above of the add function we have the following type signature.
int -> int -> int
Which states that the function takes an integer and returns a function with the signature
int -> int
that means that the returned function takes an integer and returns an integer.
This property of curried functions make them more flexible and enables partially applied functions. So we could do this to create a new function.
let incrementBy20 y = add 20 y
// val incrementBy20: y: int -> int
incrementBy20 2
// val it: int = 22
This really shows the composability of functions. If there is a library that offer a function in the tupled form then it is possible to transform it to curried form by using this kind of pattern.
let curry f x y = f (x, y)
// val curry: f: ('a * 'b -> 'c) -> x: 'a -> y: 'b -> 'c
Of course it's possible to revert the process and make a function in the tupled form.
let uncurry f (x, y) = f x y
// val uncurry: f: ('a -> 'b -> 'c) -> x: 'a * y: 'b -> 'c
Happy currying!
Top comments (0)