HOME

TheInfoList



OR:

In computer
programming language A programming language is a system of notation for writing computer programs. Most programming languages are text-based formal languages, but they may also be graphical. They are a kind of computer language. The description of a programming ...
s, a recursive data type (also known as a recursively-defined, inductively-defined or inductive data type) is a
data type In computer science and computer programming, a data type (or simply type) is a set of possible values and a set of allowed operations on it. A data type tells the compiler or interpreter how the programmer intends to use the data. Most prog ...
for values that may contain other values of the same type. Data of recursive types are usually viewed as
directed graph In mathematics, and more specifically in graph theory, a directed graph (or digraph) is a graph that is made up of a set of vertices connected by directed edges, often called arcs. Definition In formal terms, a directed graph is an ordered pa ...
s. An important application of recursion in computer science is in defining dynamic data structures such as Lists and Trees. Recursive data structures can dynamically grow to an arbitrarily large size in response to runtime requirements; in contrast, a static array's size requirements must be set at compile time. Sometimes the term "inductive data type" is used for algebraic data types which are not necessarily recursive.


Example

An example is the
list A ''list'' is any set of items in a row. List or lists may also refer to: People * List (surname) Organizations * List College, an undergraduate division of the Jewish Theological Seminary of America * SC Germania List, German rugby union ...
type, in
Haskell Haskell () is a general-purpose, statically-typed, purely functional programming language with type inference and lazy evaluation. Designed for teaching, research and industrial applications, Haskell has pioneered a number of programming lang ...
: data List a = Nil , Cons a (List a) This indicates that a list of a's is either an empty list or a cons cell containing an 'a' (the "head" of the list) and another list (the "tail"). Another example is a similar singly linked type in Java: class List This indicates that non-empty list of type E contains a data member of type E, and a reference to another List object for the rest of the list (or a null reference to indicate that this is the end of the list).


Mutually recursive data types

Data types can also be defined by
mutual recursion In mathematics and computer science, mutual recursion is a form of recursion where two mathematical or computational objects, such as functions or datatypes, are defined in terms of each other. Mutual recursion is very common in functional prog ...
. The most important basic example of this is a
tree In botany, a tree is a perennial plant with an elongated Plant stem, stem, or trunk (botany), trunk, usually supporting branches and leaves. In some usages, the definition of a tree may be narrower, including only woody plants with secondar ...
, which can be defined mutually recursively in terms of a forest (a list of trees). Symbolically: f: [1_...,_t[k.html" ;"title=".html" ;"title="[1">[1 ..., t[k">.html" ;"title="[1">[1 ..., t[k t: v f A forest ''f'' consists of a list of trees, while a tree ''t'' consists of a pair of a value ''v'' and a forest ''f'' (its children). This definition is elegant and easy to work with abstractly (such as when proving theorems about properties of trees), as it expresses a tree in simple terms: a list of one type, and a pair of two types. This mutually recursive definition can be converted to a singly recursive definition by inlining the definition of a forest: t: v [1_...,_t[k.html" ;"title=".html" ;"title="[1">[1 ..., t[k">.html" ;"title="[1">[1 ..., t[k A tree ''t'' consists of a pair of a value ''v'' and a list of trees (its children). This definition is more compact, but somewhat messier: a tree consists of a pair of one type and a list another, which require disentangling to prove results about. In Standard ML, the tree and forest data types can be mutually recursively defined as follows, allowing empty trees: datatype 'a tree = Empty , Node of 'a * 'a forest and 'a forest = Nil , Cons of 'a tree * 'a forest In Haskell, the tree and forest data types can be defined similarly: data Tree a = Empty , Node (a, Forest a) data Forest a = Nil , Cons (Tree a) (Forest a)


Theory

In
type theory In mathematics, logic, and computer science, a type theory is the formal presentation of a specific type system, and in general type theory is the academic study of type systems. Some type theories serve as alternatives to set theory as a found ...
, 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 In mathematical logic, the Peano axioms, also known as the Dedekind–Peano axioms or the Peano postulates, are axioms for the natural numbers presented by the 19th century Italian mathematician Giuseppe Peano. These axioms have been used nearly u ...
) may be defined by the Haskell datatype: data Nat = Zero , Succ Nat In type theory, we would say: nat = \mu \alpha. 1 + \alpha where the two arms of the
sum type In computer science, a tagged union, also called a variant, variant record, choice type, discriminated union, disjoint union, sum type or coproduct, is a data structure used to hold a value that could take on several different, but fixed, types. O ...
represent the Zero and Succ data constructors. Zero takes no arguments (thus represented by the
unit type In the area of mathematical logic and computer science known as type theory, a unit type is a type that allows only one value (and thus can hold no information). The carrier (underlying set) associated with a unit type can be any singleton set. ...
) 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/math> (Where the notation X /Z/math> 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 In mathematics, an isomorphism is a structure-preserving mapping between two structures of the same type that can be reversed by an inverse mapping. Two mathematical structures are isomorphic if an isomorphism exists between them. The word is ...
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/math>, and these two are
inverse function In mathematics, the inverse function of a function (also called the inverse of ) is a function that undoes the operation of . The inverse of exists if and only if is bijective, and if it exists, is denoted by f^ . For a function f\colon ...
s.


Equirecursive types

Under equirecursive rules, a recursive type \mu \alpha . T and its unrolling T mu\alpha.T/\alpha/math> 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 Type inference refers to the automatic detection of the type of an expression in a formal language. These include programming languages and mathematical type systems, but also natural languages in some branches of computer science and linguistic ...
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 Object-oriented programming (OOP) is a programming paradigm based on the concept of " objects", which can contain data and code. The data is in the form of fields (often known as attributes or ''properties''), and the code is in the form of p ...
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

Recursion is allowed in the type alias of
TypeScript TypeScript is a free and open source programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript and adds optional static typing to the language. It is designed for the development of large appl ...
.(More) Recursive Type Aliases - Announcing TypeScript 3.7 - TypeScript
/ref> Following example is allowed. type Tree = number , Tree[]; let tree: Tree = [1, [2, 3; However, recursion is not allowed in type synonyms in Miranda programming language, Miranda, OCaml (unless -rectypes flag is used or it's a record or variant), and Haskell; so for example the following Haskell types are illegal: type Bad = (Int, Bad) type Evil = Bool -> Evil Instead, it must be wrapped inside an algebraic data type (even if it only has one constructor): data Good = Pair Int Good data Fine = Fun (Bool -> Fine) This is because type synonyms, like
typedef typedef is a reserved keyword in the programming languages C, C++, and Objective-C. It is used to create an additional name (''alias'') for another data type, but does not create a new type, except in the obscure case of a qualified typedef of ...
s in C, are replaced with their definition at compile time. (Type synonyms are not "real" types; they are just "aliases" for convenience of the programmer.) But if this is attempted with a recursive type, it will loop infinitely because no matter how many times the alias is substituted, it still refers to itself, e.g. "Bad" will grow indefinitely: Bad(Int, Bad)(Int, (Int, Bad))... . Another way to see it is that a level of indirection (the algebraic data type) is required to allow the isorecursive type system to figure out when to ''roll'' and ''unroll''.


See also

*
Recursive definition In mathematics and computer science, a recursive definition, or inductive definition, is used to define the elements in a set in terms of other elements in the set ( Aczel 1977:740ff). Some examples of recursively-definable objects include fact ...
* Algebraic data type *
Inductive type In type theory, a system has inductive types if it has facilities for creating a new type from constants and functions that create terms of that type. The feature serves a role similar to data structures in a programming language and allows a ty ...
*
Node (computer science) A node is a basic unit of a data structure, such as a linked list or tree data structure. Nodes contain data and also may link to other nodes. Links between nodes are often implemented by pointers. Nodes and Trees Nodes are often arranged into ...


References

{{Data types Data types Type theory