A value is polymorphic if, depending on the context where it's used, it can take on more than one type. Polymorphism is widespread in Haskell and is a key feature of its type system.
1 Parametric polymorphism
Parametric polymorphism refers to when the type of a value contains type variables (denoted in Haskell by names starting with a lowercase letter in types) with no constraints (e.g. class constraints; see below) on them. Then the value may adopt any type that results from substituting those variables with concrete types.For example, the function
Since a parametrically polymorphic value does not "know" anything about the unconstrained type variables, it must behave the same regardless of its type. This is a somewhat limiting but extremely useful property known as parametricity.
2 Ad-hoc polymorphism
Ad-hoc polymorphism refers to when a value is able to adopt any one of a finite number of types because it, or a value it uses, has been given a separate definition for each of those types. In many languages this is called overloading, and in Haskell it is achieved via the system of type classes and class instances.
Despite the similarity of the name, Haskell's type classes are quite different from the classes of most object-oriented languages. They have more in common with interfaces, in that they specify a series of methods or values by their type signature, to be implemented by an instance declaration.So, for example, if my type can be compared for equality (most types can, but some, particularly function types, cannot) then I can give an instance declaration of the
3 Other kinds of polymorphism
There are some kinds of polymorphism that Haskell doesn't support, or at least not natively, e.g. inclusion polymorphism and subtyping, common in OO languages, where values of one type can act as values of another type.
4 Further reading
- On Understanding Types, Data Abstraction, and Polymorphism (1985), by Luca Cardelli, Peter Wegner in ACM Computing Surveys.
- Type polymorphism at Wikipedia