In
type theory, a recursive type has the general form
μα.
T where the
type variable α may appear in the type
T and stands for the entire type itself. For example, the natural numbers (see
Peano arithmetic) may be defined by the Haskell datatype: data Nat = Zero | Succ Nat In type theory, we would say: \text{nat} = \mu \alpha. 1 + \alpha where the two arms of the
sum type represent the Zero and Succ data constructors. Zero takes no arguments (thus represented by the
unit type) and Succ takes another Nat (thus another element of \mu \alpha. 1 + \alpha). There are two forms of recursive types: the so-called isorecursive types, and equirecursive types. The two forms differ in how terms of a recursive type are introduced and eliminated.
Isorecursive types With isorecursive types, the recursive type \mu \alpha . T and its expansion (or
unrolling) T[\mu \alpha.T / \alpha] (where the notation X[Y/Z] indicates that all instances of Z are replaced with Y in X) are distinct (and disjoint) types with special term constructs, usually called
roll and
unroll, that form an
isomorphism between them. To be precise: roll : T[\mu\alpha.T/\alpha] \to \mu\alpha.T and unroll : \mu\alpha.T \to T[\mu\alpha.T/\alpha], and these two are
inverse functions.
Equirecursive types Under equirecursive rules, a recursive type \mu \alpha . T and its unrolling T[\mu\alpha.T/\alpha] are
equal – that is, those two type expressions are understood to denote the same type. In fact, most theories of equirecursive types go further and essentially specify that any two type expressions with the same "infinite expansion" are equivalent. As a result of these rules, equirecursive types contribute significantly more complexity to a type system than isorecursive types do. Algorithmic problems such as type checking and
type inference are more difficult for equirecursive types as well. Since direct comparison does not make sense on an equirecursive type, they can be converted into a canonical form in O(n log n) time, which can easily be compared. Isorecursive types capture the form of self-referential (or mutually referential) type definitions seen in nominal
object-oriented programming languages, and also arise in type-theoretic semantics of objects and
classes. In functional programming languages, isorecursive types (in the guise of datatypes) are common too. ==Recursive type synonyms==