Lably
Skip to content

Recursive data type

Data type that refers to itself in its definition

  • 5 min read
  • 3 chapters

Related on Lably

Through Computer programming, Data type and Directed graph

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 type, in Haskell:

<span id="mwGQ"></span><span class="kr" id="mwGg">data</span><span class="w" id="mwGw"> </span><span class="kt" id="mwHA">List</span><span class="w" id="mwHQ"> </span><span class="n" id="mwHg">a</span><span class="w" id="mwHw"> </span><span class="ow" id="mwIA">=</span><span class="w" id="mwIQ"> </span><span class="kt" id="mwIg">Nil</span><span class="w" id="mwIw"> </span><span class="o" id="mwJA">|</span><span class="w" id="mwJQ"> </span><span class="kt" id="mwJg">Cons</span><span class="w" id="mwJw"> </span><span class="n" id="mwKA">a</span><span class="w" id="mwKQ"> </span><span class="p" id="mwKg">(</span><span class="kt" id="mwKw">List</span><span class="w" id="mwLA"> </span><span class="n" id="mwLQ">a</span><span class="p" id="mwLg">)</span>

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:

<span id="mwNQ"></span><span class="kd" id="mwNg">public</span><span class="w" id="mwNw"> </span><span class="kd" id="mwOA">class</span> <span class="nc" id="mwOQ">LinkedList</span><span class="o" id="mwOg"><</span><span class="n" id="mwOw">E</span><span class="o" id="mwPA">></span><span class="w" id="mwPQ"> </span><span class="p" id="mwPg">{</span> <span class="w" id="mwPw"> </span><span class="kd" id="mwQA">private</span><span class="w" id="mwQQ"> </span><span class="n" id="mwQg">E</span><span class="w" id="mwQw"> </span><span class="n" id="mwRA">value</span><span class="p" id="mwRQ">;</span> <span class="w" id="mwRg"> </span><span class="kd" id="mwRw">private</span><span class="w" id="mwSA"> </span><span class="n" id="mwSQ">LinkedList</span><span class="o" id="mwSg"><</span><span class="n" id="mwSw">E</span><span class="o" id="mwTA">></span><span class="w" id="mwTQ"> </span><span class="n" id="mwTg">next</span><span class="p" id="mwTw">;</span> <span class="w" id="mwUA"> </span><span class="c1" id="mwUQ">// constructor and methods...</span> <span class="p" id="mwUg">}</span>

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. The most important basic example of this is a tree, which can be defined mutually recursively in terms of a forest (a list of trees). Symbolically:

f: <span typeof="mw:Nowiki" id="mwXg">[t[1], ..., t[k]]</span> 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 <span typeof="mw:Nowiki" id="mwZg">[t[1], ..., t[k]]</span>

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:

<span id="mwcg"></span><span class="kr" id="mwcw">datatype</span> <span class="nd" id="mwdA">'a</span> <span class="kt" id="mwdQ">tree</span> <span class="p" id="mwdg">=</span> <span class="nc" id="mwdw">Empty</span> <span class="p" id="mweA">|</span> <span class="nc" id="mweQ">Node</span> <span class="kr" id="mweg">of</span> <span class="nd" id="mwew">'a</span> <span class="n" id="mwfA">*</span> <span class="nd" id="mwfQ">'a</span> <span class="n" id="mwfg">forest</span> <span class="kr" id="mwfw">and</span> <span class="nd" id="mwgA">'a</span> <span class="kt" id="mwgQ">forest</span> <span class="p" id="mwgg">=</span> <span class="nc" id="mwgw">Nil</span> <span class="p" id="mwhA">|</span> <span class="nc" id="mwhQ">Cons</span> <span class="kr" id="mwhg">of</span> <span class="nd" id="mwhw">'a</span> <span class="n" id="mwiA">tree</span> <span class="n" id="mwiQ">*</span> <span class="nd" id="mwig">'a</span> <span class="n" id="mwiw">forest</span>

In Haskell, the tree and forest data types can be defined similarly:

<span id="mwjw"></span><span class="kr" id="mwkA">data</span><span class="w" id="mwkQ"> </span><span class="kt" id="mwkg">Tree</span><span class="w" id="mwkw"> </span><span class="n" id="mwlA">a</span><span class="w" id="mwlQ"> </span><span class="ow" id="mwlg">=</span><span class="w" id="mwlw"> </span><span class="kt" id="mwmA">Empty</span> <span class="w" id="mwmQ"> </span><span class="o" id="mwmg">|</span><span class="w" id="mwmw"> </span><span class="kt" id="mwnA">Node</span><span class="w" id="mwnQ"> </span><span class="p" id="mwng">(</span><span class="n" id="mwnw">a</span><span class="p" id="mwoA">,</span><span class="w" id="mwoQ"> </span><span class="kt" id="mwog">Forest</span><span class="w" id="mwow"> </span><span class="n" id="mwpA">a</span><span class="p" id="mwpQ">)</span> <span class="kr" id="mwpg">data</span><span class="w" id="mwpw"> </span><span class="kt" id="mwqA">Forest</span><span class="w" id="mwqQ"> </span><span class="n" id="mwqg">a</span><span class="w" id="mwqw"> </span><span class="ow" id="mwrA">=</span><span class="w" id="mwrQ"> </span><span class="kt" id="mwrg">Nil</span> <span class="w" id="mwrw"> </span><span class="o" id="mwsA">|</span><span class="w" id="mwsQ"> </span><span class="kt" id="mwsg">Cons</span><span class="w" id="mwsw"> </span><span class="p" id="mwtA">(</span><span class="kt" id="mwtQ">Tree</span><span class="w" id="mwtg"> </span><span class="n" id="mwtw">a</span><span class="p" id="mwuA">)</span><span class="w" id="mwuQ"> </span><span class="p" id="mwug">(</span><span class="kt" id="mwuw">Forest</span><span class="w" id="mwvA"> </span><span class="n" id="mwvQ">a</span><span class="p" id="mwvg">)</span>

Sign in to keep reading

2 more chapters are free with a Lably account.

More in Computing and communication