The purpose of eta reduction (also written \(\eta\)-reduction) is to drop an abstraction over a function to simplify it. This is possible when there is nothing more that a function can do to its argument. For example, imagine that we have a simple function \( f\ x = g\ x \). Both \(g\) and \(f\) take the same argument, \(x\), and the function application function results in the same value (specified by the equality symbol). Since both \(f\) and \(g\) take the same argument and produce the same result, we can simplify the equation to just \(f = g\). In lambda calculus, this simplification is called \(\eta\)-reduction.

More precisely, \(\eta\)-reduction allows you to convert between \(\lambda x.(f\ x)\) and \(f\) whenever \(x\) is not a free variable in \(f\). That is, \(f = \lambda x(f\ x)\). Let’s look at a more practical example from the book PureScript by Example.

In functional languages based on lambda calculus, all functions take exactly one argument. PureScript is no different. For example, consider the function insertEntry that inserts an entry into an address book. This function takes an Entry and an AddressBook as a parameter, and returns a new AddressBook with the entry parameter inserted into it. This function has a type signature of insertEntry :: Entry -> AddressBook -> AddressBook, which specifies that the function insertEntry takes parameters of type Entry and AddressBook and returns a result of AddressBook.

We make some simplifying assumptions here by assuming that AddressBook is implemented as a simple list. We can therefore use concatenation (or list construction) to implement insertEntry by concatenating the entry to the address book using the concatenation function Cons. This results in the following type signature and implementation for insertEntry.

insertEntry :: Entry -> AddressBook -> AddressBook
insertEntry entry book = Cons entry book

This function is implemented by passing the book and entry parameters to the Cons function to concatenate them together. If we remove the parameter book from both sides of the function definition, we end up with a function insertEntry entry and a function Cons entry. Both of these functions can still be called with book as a parameter. Since these two functions are equivalent and they take the same parameter, we can use \(\eta\)-reduction to completely eliminate the parameter book from the function definition.

insertEntry :: Entry -> AddressBook -> AddressBook
insertEntry entry = Cons entry

By the same reasoning, we can further reduce the function to remove the entry argument. This results in the following function:

insertEntry :: Entry -> AddressBook -> AddressBook
insertEntry = Cons

We now have a very simple implementation for insertEntry — it is just Cons on a list.