Skip to content

Anonymous Functions

When we write a function such as

double x = 2 * x

which is a function that doubles its argument, we actually do two things in one go: we define the function that doubles its argument—this function has no name—and then we assign it to the variable double so we have a name by which we can refer to the function. This is completely analogous to assigning the value of some integer or string expression to a variable.

Functions without names are called anonymous functions or lambda expressions. The above function as an anonymous function is written like this:

\x -> 2 * x

The backslash at the beginning looks a little bit like a \(\lambda\) with its left leg missing. This is the symbol used in Haskell to introduce an anonymous function definition. What follows is the list of arguments. Here, there is one argument, x. Then we have the arrow, ->, and finally the value of the function given this argument, 2 * x.

The equation

double x = 2 * x

is really just syntactic sugar1 for

double = \x -> 2 * x

We create a function that doubles its argument and bind this function to the name double. In mathematics, you sometimes see functions written like this:

\[\textit{double} : \mathbb{Z} \rightarrow \mathbb{Z}, x \mapsto 2x.\]

The first part says that the function maps integers to integers. The second part specifies the mapping. It says the same as if we had written \(\textit{double}(x) = 2x\). If you write the type signature of double and its definition,

double :: Int -> Int
double = \x -> 2 * x

you get the Haskell equivalent of these two parts of the function definition.

GHCi
>>> double = \x -> 2 * x
>>> double 5
10

We can also define anonymous multi-argument functions. The function

\x y -> x * y

takes two arguments, x and y, and returns their product. The definition

multiply x y = x * y

is once again just syntactic sugar for

multiply = \x y -> x * y
GHCi
>>> multiply = \x y -> x * y
>>> multiply 5 3
15

Why do we care about the ability to define anonymous functions? Sometimes we need to build a custom function that we need once, as an argument to another function, but nowhere else. In that case, it's useful not to give that function a name and simply pass it directly to the other function. For example, we will later discuss the filter function, which allows us to extract the list of all elements in a list that meet a certain condition. Say, I have the list of all positive integers between 1 and 1000000, written [1..1000000] in Haskell. Let's say I want to extract from it all even integers between 100 and 200. The filter function has the following type (don't worry that we haven't formally talked about lists yet, this should be fairly easy to understand):

filter :: (a -> Bool) -> [a] -> [a]

Its first argument is a Boolean predicate, a function that checks whether a value of type a has a certain property. The second argument is a list of values of type a. What filter returns is the list of all values in this list that have the desired property, for which the predicate is True. For example, we have

GHCi
>>> even 1
False
>>> even 2
True
>>> filter even [1..10]
[2,4,6,8,10]

Now we don't only want to extract the even numbers but the even numbers between 100 and 200. To express this condition, we need a predicate that tests all of these conditions at once. We could do this like this:

GHCi
>>> select x = even x && x >= 100 && x <= 200
>>> filter select [1..1000000]
[100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138
,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178
,180,182,184,186,188,190,192,194,196,198,200]

but this is exactly what we would like to avoid—we're defining the function select only for use within the filter expression. This is where anonymous functions come in handy because we can simply write

GHCi
>>> filter (\x -> even x && x >= 100 && x <= 200) [1..1000000]
[100,102,104,106,108,110,112,114,116,118,120,122,124,126,128,130,132,134,136,138
,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178
,180,182,184,186,188,190,192,194,196,198,200]

  1. "Syntactic sugar" is a term commonly used to refer to a feature in a language's syntax that does not add a new capability to the language but makes an existing capability more convenient to use.