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.