F# Functions Explained – Currying & Partial Application

This is our second blog post in a series of posts about using F# to write simpler, safer, production-quality code. Read the first part here.

One of the most surprising parts of F# is the way it handles functions. Basically, each function in F# always takes one input parameter and gives one output value. They are basically functions in the mathematical sense, transforming one input type to one output type.

Function signatures in F# are shown in this format:

print: int -> string

In this case, print is a function that transforms integers into strings: in other words, takes an integer input and returns a string.

That being said, code like this is perfectly fine:

let add a b =
    a + b

// This works
add 3 4
-> 7

If you look at the function signature of add, it will be something strange like:

add: int -> int -> int

This was greek to me at first. I started to understand it after some research. In this case, add isn’t a function that takes two numbers and returns their sum. It’s a function that has one input (the first integer) and returns another function. This (returned) function takes one input value (the second integer) and returns the sum of the two integers.

Calling add with two arguments results in two function evaluations.

add 2 3
-> 5
// This is the same as
((add 2) 3)
-> 5

This means you can call add with only one argument.

let increment = add 1
increment: int -> int

You can now use increment as if it’s a normal function that you defined yourself.

increment 4
-> 5

Sidenote: This naturally leads to a style of programming where you always keep the most important argument (usually the main data structure that you give as the input) to any function as its last argument. It makes function composition much easier. Pipelining[1] is another good reason to do this!

If you ever see a function like this, you’re probably doing it wrong:

let add (a, b) =
    a + b

This basically says that add is a function that takes one Tuple of two ints and returns another int. Make sure that when you do write code like this, you mean to do it and you’re not writing it by accident; just because you’re used to putting function arguments in brackets!

Technically, this style of functional programming is called currying with partial application.

This can be a great way to encapsulate components and hide unnecessary implementation details. Lets look at an actual use case:

/// User Validator requires `userType` as an argument
let userValidator userType user =
    // Internal validation rules for the user object

/// You can *fix* the `userType` to `NormalUser` like so:
let normalUserValidator = userValidator UserType.NormalUser

/// Your controller or view codebase only uses the wrapped validator
if normalUserValidator currentUser then
    "Do Something with valid user"
    "The normal user is invalid"

This can be used to implement a lot of ‘patterns’ that are quite complex in a non-functional language. It is a natural way to implement decorators, or do dependency injection, for example.

You should watch this talk by Jon Carmack where he discusses his experiments with Haskell; he talks about using a similar technique of passing around partially applied functions to manage game state. Interesting stuff!

Feel free to reach out to me if you have any questions regarding F#. You can email me at ankit (at) cleartax.in. By the way, ClearTax is hiring! You should really join our team if you want to work with F# 🙂

  1. A topic I’m planning to devote a whole blog post to! In the meanwhile, you can read more about it here.  ↩

(Visited 727 times, 1 visits today)
Comments are closed.