Inductive data types
The inductive
keyword is reserved for declaring inductive data types.
An inductive type declaration requires a unique name for its type and
its constructors, functions for building its terms. Constructors can be
used as normal identifiers and also in patterns. As shown later, one can
also provide type parameters to widen the family of inductive types one
can define in Juvix.
The simplest inductive type is the Empty
type with no constructors.
inductive Empty {};
In the following example, we declare the inductive type Nat
, the unary
representation of natural numbers. This type comes with two data
constructors, namely zero
and suc
. A term of the type Nat
is the
number one, represented by suc zero
or the number two represented by
suc (suc zero)
, etc.
inductive Nat {
zero : Nat;
suc : Nat → Nat;
};
The way to use inductive types is by declaring functions by pattern matching. Let us define, for example, the function for adding two natural numbers.
inifl 6 +;
+ : Nat → Nat → Nat;
+ zero b ≔ b;
+ (suc a) b ≔ suc (a + b);
As mentioned earlier, an inductive type may have type parameters. The
canonical example is the polymorphic type List
. The type List
is the
inductive type that considers the type of the elements in the list as a
parameter. A constructor to build the empty list, that is the base case,
and another constructor to enlarge the list, we usually called it
cons
. One possible definition for this type is the following type
taken from the Juvix standard library:
infixr 5 ∷;
inductive List (A : Type) {
nil : List A;
∷ : A → List A → List A;
};
elem : {A : Type} → (A → A → Bool) → A → List A → Bool;
elem _ _ nil ≔ false;
elem eq s (x ∷ xs) ≔ eq s x || elem eq s xs;
To see more examples of inductive types and how to use them, please check out the Juvix standard library