LIGO supports simple polymorphism when introducing declarations. This allows to write functions parametric on a type that can be later instantiated to concrete types.
For any given type
t, there is a canonical function of type
t -> t
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
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.
_a 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 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
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: