# Inductive Types #

The main way of introducing new types in Lean is through inductive types. An inductive type is a type
which is specified by saying how to construct terms of that type. Concretely, we specify the types of
a set of `constructors`

all of which have *final codomain* the type being constructed.

When an inductive type is defined, Lean automatically generates a *recursor* for that type, which allows defining by cases, matching, and induction on terms of that type.

## Enumerated Types #

Enumerated types are a special case of inductive types where the constructors have no arguments. We simply list the terms of that type.

An enumerated type for the answers to a yes/no question.

- yes: Waffle.Answer
- no: Waffle.Answer
- maybe: Waffle.Answer

## Instances For

## Equations

- Waffle.instReprAnswer = { reprPrec := Waffle.reprAnswer✝ }

## Equations

- Waffle.instInhabitedAnswer = { default := Waffle.Answer.yes }

## Equations

- Waffle.instDecidableEqAnswer x y = if h : Waffle.Answer.toCtorIdx x = Waffle.Answer.toCtorIdx y then isTrue ⋯ else isFalse ⋯

Some terms introduced when an inductive type is defined. The last two depended on the classes `Repr`

and `Inhabited`

being derived for the type.

```
#check Answer -- Type
#check Answer.yes -- Answer
#eval Answer.yes -- Waffle.Answer.yes
#eval (default : Answer) -- Waffle.Answer.yes
```

A function defined by cases which disagrees with the given answer.

## Equations

- Waffle.disagree x = match x with | Waffle.Answer.yes => Waffle.Answer.no | Waffle.Answer.no => Waffle.Answer.yes | Waffle.Answer.maybe => Waffle.Answer.maybe

## Instances For

The `disagree`

function is defined by cases on the argument. The definition is rewritten by Lean in terms of the `rec`

function, which is automatically generated by Lean for each inductive type. The `rec`

function is a *recursor* for the type, which allows defining by cases, matching, and induction on terms of that type.

```
#eval disagree Answer.yes -- Waffle.Answer.no
#reduce disagree -- fun x => Answer.rec Answer.no Answer.yes Answer.maybe x
#check Answer.rec -- {motive : Answer → Sort u_1} → motive Answer.yes → motive Answer.no → motive Answer.maybe → (t : Answer) → motive t
```

The type of the recursor looks complicated because we can recursively define *dependent functions* on the inductive type answer, i.e., a function `f`

which takes an argument of type `x: Answer`

and returns a value whose type depends on `x`

. The `motive`

argument specifies the type of `f x`

for `x: Answer`

.

**Note**: You should think of the word `motive`

as corresponding to the english word `motif`

, not the english word `motive`

. The `motive`

encodes the type of the function we are defining, not the reason for defining it.

Recursive definitions simplify if we are defining a (non-dependent) function on the type. Here the motive is a constant function. For example, to define a function `Answer → String`

we take as motive `fun _ => String`

.
In this case we see the type of the recursor is simplified.

```
#check Answer.rec (motive := fun _ => String) -- String → String → String → Answer → String
```

Indeed the above is easy to interpret. The recursor takes as input the value of the function being defined on the three constructors and returns a function from `Answer`

to `String`

.

If an answer is equal to its disagreement, then it must be `maybe`

.

## Structures #

Another simple kind of inductive type is a `Structure`

, whose terms correspond to values of specified fields of given types.

A structure for answers with explanations

## Instances For

An element of the type can be constructed using special syntax which is similar to a tuple but with left and right angle brackets instead of parentheses.

```
example : Answer := ⟨true, "I agree"⟩
```

When a structure is defined, a constructor named `mk`

is automatically generated. The constructor is a function which takes the arguments of the structure in the order they are declared and returns a term of the structure type.

Further, projections onto each of the fields are defined as functions named after the field. As with any induction type, a recursor is automatically generated for the structure.

```
#check Answer -- Type
#check Answer.agree -- Answer → Bool
#check Answer.explanation -- Answer → String
#check Answer.mk -- Bool → String → Answer
#check Answer.rec -- {motive : Answer → Sort u} → ((agree : Bool) → (explanation : String) → motive { agree := agree, explanation := explanation }) → (t : Answer) → motive t
```

We can rewrite the structure `Answer`

in terms of inductive types. In this case we have to define the projections manually.

- mk: Bool → String → VerboseExplained.Answer

## Instances For

## Equations

- VerboseExplained.Answer.agree x = match x with | VerboseExplained.Answer.mk agree a => agree

## Instances For

## Equations

- VerboseExplained.Answer.explanation x = match x with | VerboseExplained.Answer.mk a exp => exp

## Instances For

## "Genuine" Inductive Types #

Our earlier examples had two degenerate forms of inductive types. The main point of inductive types is that terms of such a type can be formed using terms of the same type recursively. For example, we can construct an `Answer`

type which includes a constructor that adds an explanation to an existing answer. Note that the existing answer itself can be an `Answer`

with an explanation.

- yes: LongWinded.Answer
- no: LongWinded.Answer
- maybe: LongWinded.Answer
- explained: String → LongWinded.Answer → LongWinded.Answer

## Instances For

## Equations

- LongWinded.instInhabitedAnswer = { default := LongWinded.Answer.yes }

## Equations

- LongWinded.instReprAnswer = { reprPrec := LongWinded.reprAnswer✝ }

An example of an answer

## Equations

## Instances For

An example of an answer with nested explanations

## Equations

- LongWinded.egAnswerLong = LongWinded.Answer.explained "Let me play the devil's advocate" (LongWinded.Answer.explained "This is silly" LongWinded.Answer.no)

## Instances For

Another example, to illustrate notation

## Equations

## Instances For

Here is an example of an answer with nested explanations.

```
#eval egAnswerLong /- LongWinded.Answer.explained
"Let me play the devil's advocate"
(LongWinded.Answer.explained "This is silly" (LongWinded.Answer.no)) -/
```

A function that disagrees with an answer. The explanation is ridiculed.

## Equations

- LongWinded.disagree LongWinded.Answer.yes = LongWinded.Answer.no
- LongWinded.disagree LongWinded.Answer.no = LongWinded.Answer.yes
- LongWinded.disagree LongWinded.Answer.maybe = LongWinded.Answer.maybe
- LongWinded.disagree (LongWinded.Answer.explained a a_1) = LongWinded.Answer.explained ("It would be silly to say `" ++ a ++ "'") (LongWinded.disagree a_1)

## Instances For

We can again define a function that disagrees with an answer by cases. In this case the definition is recursive, so the function in the `Answer.explained exp ans`

case depends on the recursive call to `disagree`

on `ans`

.

```
#eval disagree egAnswerLong /- LongWinded.Answer.explained
"It would be silly to say `Let me play the devil's advocate'"
(LongWinded.Answer.explained "It would be silly to say `This is silly'" (LongWinded.Answer.yes)) -/
```

A string explanation from the answer, reversing the concatenation of all explanations and adding one based on the answer.

## Equations

- LongWinded.explanation LongWinded.Answer.yes = "I agree"
- LongWinded.explanation LongWinded.Answer.no = "I disagree"
- LongWinded.explanation LongWinded.Answer.maybe = "I don't know"
- LongWinded.explanation (LongWinded.Answer.explained a a_1) = LongWinded.explanation a_1 ++ " because " ++ a

## Instances For

We can similarly define a function that gives a string explanation from the answer, reversing the concatenation of all explanations and adding one based on the answer.

```
#eval explanation egAnswerLong -- "I disagree because This is silly because Let me play the devil's advocate"
```

The recursor in such a case has to enable recursive definitions. To see how this happnes, we can check the type of the recursor. We consider the case where we are defining a function from `Answer`

to `String`

.

```
#check @Answer.rec (motive := fun _ => String) -- String → String → String → (String → Answer → String → String) → Answer → String
```

The recursor has type `String → String → String → (String → Answer → String → String) → Answer → String`

. The first three arguments are the values of the function for the three constructors without an explanation. The last argument is a function that takes the value of the function for the explanation case, the answer, and the string explanation of the answer, and returns the value of the function for the answer. The last argument is the answer itself.

## Indexed Inductive Types #

A more complex variant of inductive types is an indexed inductive type. Here we introduce a family of inductive types with the constructors giving terms having types lying in the family. As an example, we define an indexed inductive type capturing `≤`

on the type `Waffle.Answer`

.

As this gives a proposition for a pair of answers, the family has type `Answer → Answer → Prop`

. The first two constructors are `Answer.le.no_le`

and `Answer.le.le_yes`

giving the propositions `Answer.no ≤ ans`

and `ans ≤ Answer.yes`

for any `ans`

. The constructor `Answer.le.refl`

gives the proposition `ans ≤ ans`

for any `ans`

.

- no_le: ∀ (ans : Waffle.Answer), Waffle.Answer.le Waffle.Answer.no ans
- le_yes: ∀ (ans : Waffle.Answer), Waffle.Answer.le ans Waffle.Answer.yes
- refl: ∀ (ans : Waffle.Answer), Waffle.Answer.le ans ans

## Instances For

An instance associating `≤`

to `Answer.le`

## Equations

- Waffle.instLEAnswer = { le := Waffle.Answer.le }

transitivity of the relation `≤`

on answers

`Prop`

versus `Type`

#

To illustrate the difference between propositions and general types, we define a variant of the `Answer`

type in the `Prop`

universe. The constructors are the same as for `Waffle.Answer`

, but the type is `Prop`

instead of `Type`

.

`Answer`

as an inductive prop

- yes: PropAnswer.Answer
- no: PropAnswer.Answer
- maybe: PropAnswer.Answer

## Instances For

We see that what we have defined is a proposition.

```
#check Answer -- PropAnswer.Answer : Prop
```

We can try to define a function `Answer → Bool`

by cases. This gives an error message, as the recursor for `Answer`

is not defined for general types.

```
def generous : Answer → Bool
| Answer.yes => true
| Answer.no => false
| Answer.maybe => true
```

gives error message

```
tactic 'cases' failed, nested error:
tactic 'induction' failed, recursor 'PropAnswer.Answer.casesOn' can only eliminate into Prop
motive: Answer → Sort ?u.9737
h_1: Unit → motive Answer.yes
h_2: Unit → motive Answer.no
h_3: Unit → motive Answer.maybe
⊢ motive x✝
after processing
_
the dependent pattern matcher can solve the following kinds of equations
- <var> = <term> and <term> = <var>
- <term> = <term> where the terms are definitionally equal
- <constructor> = <constructor>, examples: List.cons x xs = List.cons y ys, and List.cons x xs = List.nil
```

The conceptual reason for this is that two terms of a proposition are definitionally equal. But the definition by cases would give a function that is not constant on the proposition, so equal arguments will give unequal results, a logical contradiction.

The formal reason lies in the type of the recursor constructed for the proposition. The recursor is defined for propositions, not for general types. The type of the recursor is

```
#check Answer.rec /- PropAnswer.Answer.rec {motive : Answer → Prop} (yes : motive Answer.yes) (no : motive Answer.no)
(maybe : motive Answer.maybe) (t : Answer) : motive t
-/
```

In particular if we wish to define a term `Answer → α`

, then the motive must be `fun _ ↦ α`

and so `α`

must be a proposition.