# Polymorphism

LIGO supports simple polymorphism when introducing declarations. This allows to write functions parametric on a type that can be later instantiated to concrete types.

## The identity function

For any given type `t`

, there is a canonical function of type `t -> t`

(function from `t`

to `t`

): it takes an argument, and returns it
immediately. For instance, we can write the identity function for
`int`

as follows:

However, if we would want to use the same function on a different
type, such as `nat`

, we will need to write a new definition:

If we read carefully, we see that there is almost no difference
between `id`

and `idnat`

: it is just the type that changes, but for
the rest, the body of the function remains the same.

Thanks to parametric polymorphism, we can write a single function declaration that works for both cases.

Here `T`

is a type variable which can be generalised. In general,
types prefixed with `_`

are treated as generalisable.

We can then use this function directly in different types by just regular application:

During compilation, LIGO will monomorphise the polymorphic functions into specific instances, resulting in Michelson code that does not contain polymorphic function declarations anymore.

## Polymorphism with parametric types

Polymorphism is especially useful when writing functions over parametric types, which include built-in types like lists, sets, and maps.

As an example, we will see how to implement list reversing parametrically on any type, rather than just on lists of a specific type.

Similar to the `id`

example, we can introduce a type variable that can
be generalised. We will write a direct version of the function using
an accumulator, but the reader can experiment with different
variations by using `List`

combinators.

We use an accumulator variable `acc`

to keep the elements of the list
processed, consing each element on it. As with the identity function,
we can then use it directly in different types: