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
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
parameters of type
AddressBook and returns a result of
We make some simplifying assumptions here by assuming that
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 :: Entry -> AddressBook -> AddressBook insertEntry entry book = Cons entry book
This function is implemented by passing the
Cons function to concatenate them together. If we remove the
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
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.