Predicative Polymorphism
   HOME

TheInfoList



OR:

In programming languages and type theory, parametric polymorphism allows a single piece of code to be given a "generic" type, using variables in place of actual types, and then instantiated with particular types as needed. Parametrically polymorphic functions and data types are sometimes called generic functions and generic datatypes, respectively, and they form the basis of generic programming. Parametric polymorphism may be contrasted with ad hoc polymorphism. Parametrically polymorphic definitions are ''uniform'': they behave identically regardless of the type they are instantiated at. In contrast, ad hoc polymorphic definitions are given a distinct definition for each type. Thus, ad hoc polymorphism can generally only support a limited number of such distinct types, since a separate implementation has to be provided for each type.


Basic definition

It is possible to write functions that do not depend on the types of their arguments. For example, the identity function \mathsf(x) = x simply returns its argument unmodified. This naturally gives rise to a family of potential types, such as \mathsf \to \mathsf, \mathsf \to \mathsf, \mathsf \to \mathsf, and so on. Parametric polymorphism allows \mathsf to be given a single, most general type by introducing a universally quantified type variable: :\mathsf : \forall \alpha. \alpha \to \alpha The polymorphic definition can then be ''instantiated'' by substituting any concrete type for \alpha, yielding the full family of potential types. The identity function is a particularly extreme example, but many other functions also benefit from parametric polymorphism. For example, an \mathsf function that appends two lists does not inspect the elements of the list, only the list structure itself. Therefore, \mathsf can be given a similar family of types, such as (( mathsf mathsf \to mathsf, (( mathsf mathsf \to mathsf, and so on, where /math> denotes a list of elements of type T. The most general type is therefore :\mathsf : \forall \alpha. (
alpha Alpha (uppercase , lowercase ; grc, ἄλφα, ''álpha'', or ell, άλφα, álfa) is the first letter of the Greek alphabet. In the system of Greek numerals, it has a value of one. Alpha is derived from the Phoenician letter aleph , whic ...
alpha Alpha (uppercase , lowercase ; grc, ἄλφα, ''álpha'', or ell, άλφα, álfa) is the first letter of the Greek alphabet. In the system of Greek numerals, it has a value of one. Alpha is derived from the Phoenician letter aleph , whic ...
\to
alpha Alpha (uppercase , lowercase ; grc, ἄλφα, ''álpha'', or ell, άλφα, álfa) is the first letter of the Greek alphabet. In the system of Greek numerals, it has a value of one. Alpha is derived from the Phoenician letter aleph , whic ...
/math> which can be instantiated to any type in the family. Parametrically polymorphic functions like \mathsf and \mathsf are said to be ''parameterized over'' an arbitrary type \alpha. Both \mathsf and \mathsf are parameterized over a single type, but functions may be parameterized over arbitrarily many types. For example, the \mathsf and \mathsf functions that return the first and second elements of a pair, respectively, can be given the following types: : \begin \mathsf & : \forall \alpha. \forall \beta. (\alpha, \beta) \to \alpha \\ \mathsf & : \forall \alpha. \forall \beta. (\alpha, \beta) \to \beta \end In the expression \mathsf((3, \mathsf)), \alpha is instantiated to \mathsf and \beta is instantiated to \mathsf in the call to \mathsf, so the type of the overall expression is \mathsf. The
syntax In linguistics, syntax () is the study of how words and morphemes combine to form larger units such as phrases and sentences. Central concerns of syntax include word order, grammatical relations, hierarchical sentence structure ( constituency) ...
used to introduce parametric polymorphism varies significantly between programming languages. For example, in some programming languages, such as Haskell, the \forall \alpha quantifier is implicit and may be omitted. Other languages require types to be instantiated explicitly at some or all of a parametrically polymorphic function's call sites.


History

Parametric polymorphism was first introduced to programming languages in ML in 1975. Today it exists in
Standard ML Standard ML (SML) is a general-purpose, modular, functional programming language with compile-time type checking and type inference. It is popular among compiler writers and programming language researchers, as well as in the development of the ...
,
OCaml OCaml ( , formerly Objective Caml) is a general-purpose programming language, general-purpose, multi-paradigm programming language which extends the Caml dialect of ML (programming language), ML with object-oriented programming, object-oriented ...
, F#, Ada, Haskell,
Mercury Mercury commonly refers to: * Mercury (planet), the nearest planet to the Sun * Mercury (element), a metallic chemical element with the symbol Hg * Mercury (mythology), a Roman god Mercury or The Mercury may also refer to: Companies * Merc ...
, Visual Prolog, Scala, Julia, Python, TypeScript, C++ and others. Java, C#, Visual Basic .NET and
Delphi Delphi (; ), in legend previously called Pytho (Πυθώ), in ancient times was a sacred precinct that served as the seat of Pythia, the major oracle who was consulted about important decisions throughout the ancient classical world. The oracle ...
have each introduced "generics" for parametric polymorphism. Some implementations of type polymorphism are superficially similar to parametric polymorphism while also introducing ad hoc aspects. One example is C++ template specialization.


Predicativity, impredicativity, and higher-rank polymorphism


Rank-1 (predicative) polymorphism

In a '' predicative'' type system (also known as a '' prenex polymorphic'' system), type variables may not be instantiated with polymorphic types. Predicative type theories include Martin-Löf type theory and NuPRL. This is very similar to what is called "ML-style" or "Let-polymorphism" (technically ML's Let-polymorphism has a few other syntactic restrictions). This restriction makes the distinction between polymorphic and non-polymorphic types very important; thus in predicative systems polymorphic types are sometimes referred to as ''type schemas'' to distinguish them from ordinary (monomorphic) types, which are sometimes called ''monotypes''. A consequence of predicativity is that all types can be written in a form that places all quantifiers at the outermost (prenex) position. For example, consider the \mathsf function described above, which has the following type: :\mathsf : \forall \alpha. (
alpha Alpha (uppercase , lowercase ; grc, ἄλφα, ''álpha'', or ell, άλφα, álfa) is the first letter of the Greek alphabet. In the system of Greek numerals, it has a value of one. Alpha is derived from the Phoenician letter aleph , whic ...
alpha Alpha (uppercase , lowercase ; grc, ἄλφα, ''álpha'', or ell, άλφα, álfa) is the first letter of the Greek alphabet. In the system of Greek numerals, it has a value of one. Alpha is derived from the Phoenician letter aleph , whic ...
\to
alpha Alpha (uppercase , lowercase ; grc, ἄλφα, ''álpha'', or ell, άλφα, álfa) is the first letter of the Greek alphabet. In the system of Greek numerals, it has a value of one. Alpha is derived from the Phoenician letter aleph , whic ...
/math> In order to apply this function to a pair of lists, a concrete type T must be substituted for the variable \alpha such that the resulting function type is consistent with the types of the arguments. In an ''impredicative'' system, T may be any type whatsoever, including a type that is itself polymorphic; thus \mathsf can be applied to pairs of lists with elements of any type—even to lists of polymorphic functions such as \mathsf itself. Polymorphism in the language ML is predicative. This is because predicativity, together with other restrictions, makes the type system simple enough that full type inference is always possible. As a practical example,
OCaml OCaml ( , formerly Objective Caml) is a general-purpose programming language, general-purpose, multi-paradigm programming language which extends the Caml dialect of ML (programming language), ML with object-oriented programming, object-oriented ...
(a descendant or dialect of ML) performs type inference and supports impredicative polymorphism, but in some cases when impredicative polymorphism is used, the system's type inference is incomplete unless some explicit type annotations are provided by the programmer.


Higher-rank polymorphism

Some type systems support an impredicative function type constructor even though other type constructors remain predicative. For example, the type (\forall \alpha. \alpha \rightarrow \alpha) \rightarrow T is permitted in a system that supports higher-rank polymorphism, even though forall \alpha. \alpha \rightarrow \alpha/math> may not be. A type is said to be of rank ''k'' (for some fixed integer ''k'') if no path from its root to a \forall quantifier passes to the left of ''k'' or more arrows, when the type is drawn as a tree. A type system is said to support rank-''k'' polymorphism if it admits types with rank less than or equal to ''k''. For example, a type system that supports rank-2 polymorphism would allow (\forall \alpha. \alpha \rightarrow \alpha) \rightarrow T but not ((\forall \alpha. \alpha \rightarrow \alpha) \rightarrow T) \rightarrow T. A type system that admits types of arbitrary rank is said to be "rank-''n'' polymorphic". Type inference for rank-2 polymorphism is decidable, but for rank-3 and above, it is not.


Impredicative polymorphism

''Impredicative polymorphism'' (also called ''first-class polymorphism'') is the most powerful form of parametric polymorphism. In formal logic, a definition is said to be impredicative if it is self-referential; in type theory, it refers to the ability for a type to be in the domain of a quantifier it contains. This allows the instantiation of any type variable with any type, including polymorphic types. An example of a system supporting full impredicativity is System F, which allows instantiating \forall \alpha. \alpha \to \alpha at any type, including itself. In type theory, the most frequently studied impredicative typed λ-calculi are based on those of the lambda cube, especially System F.


Bounded parametric polymorphism

In 1985, Luca Cardelli and Peter Wegner recognized the advantages of allowing ''bounds'' on the type parameters. Many operations require some knowledge of the data types, but can otherwise work parametrically. For example, to check whether an item is included in a list, we need to compare the items for equality. In
Standard ML Standard ML (SML) is a general-purpose, modular, functional programming language with compile-time type checking and type inference. It is popular among compiler writers and programming language researchers, as well as in the development of the ...
, type parameters of the form ''’’a'' are restricted so that the equality operation is available, thus the function would have the type ''’’a'' × ''’’a'' list → bool and ''’’a'' can only be a type with defined equality. In Haskell, bounding is achieved by requiring types to belong to a
type class In computer science, a type class is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types. Such a constraint typically involves a type class T and ...
; thus the same function has the type \mathrm \, \alpha \, \Rightarrow \alpha \, \rightarrow \left alpha \right\rightarrow \mathrm in Haskell. In most object-oriented programming languages that support parametric polymorphism, parameters can be constrained to be
subtype Subtype may refer to: * Viral subtypes, such as Subtypes of HIV * Subtyping In programming language theory, subtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is ...
s of a given type (see
Subtype polymorphism In programming language theory, subtyping (also subtype polymorphism or inclusion polymorphism) is a form of type polymorphism in which a subtype is a datatype that is related to another datatype (the supertype) by some notion of substitutability ...
and the article on Generic programming).


See also

* Parametricity * Polymorphic recursion * Type class#Higher-kinded polymorphism * Trait (computer programming)


Notes


References

* * . * * . * . * * * {{Data types Generic programming Polymorphism (computer science) Type theory