# Lecture 2: Martin-Löf’s Type Theory, System F, Calculus of Constructions

Teachers: Bruno Barras & Matthieu Sozeau

## Martin-Löf’s Type Theory

Martin Löf’s idea: set apart types and terms, they have distinct judgements:

Γ ⊢ A \; type\\ Γ⊢M:A\\ Γ ⊢ A = B \quad \text{only on well-typed terms) }\\ Γ⊢M=N:A

(types have a specific judgment) (equality

And then:

• formation rules (for $∏$)
• introduction rules (for $λ$)
• elmination rules (for application)
• computation rules ($β$-reduction)

### Type constructors

• Logical connectives: e.g. $\cfrac{Γ⊢A \; type \qquad Γ⊢B \; type} {Γ⊢A×B \; type}$
• Universes, …
• Propositional Equality:

\cfrac{Γ ⊢ a, b:A}{Γ ⊢ a=b \; type}\qquad \cfrac{Γ ⊢ a:A}{Γ ⊢ r(a): a=a}\qquad \cfrac{Γ⊢p : a=b \qquad Γ,x:A⊢C(x) \; type \qquad Γ⊢e:C(a)}{Γ⊢J(p,C,e) : C(b)}

## System F

Invented by Girard and Reynolds independently (1972/74).

New type former: polymorphism:

\underbrace{∀α}_{\text{all possible substitution of a type for } α}. \, τ
\cfrac{Γ⊢M :τ \qquad α \text{ not free in } Γ}{Γ⊢Λα.M :∀α.τ}\qquad \cfrac{Γ⊢M :∀α.τ}{ Γ⊢M τ' :τ[τ'/α]}

Why is it useful? Enables us to encode second-order arithmetic: e.g. natural numbers:

ℕ \, ≝ \, ∀α.α → (α → α) → α\\ [n] \, ≝ \, λx.λf.f^n x

But, limitatiions: cannot encode equality (between numbers, etc…): enables us to construct functions, but not reason on them.

Polymorphism also called impredicativity: allows self-application! May seem frightening (we’re coming close to Russel’s paradox?), but not really: System F is not set-theoretic.

## Calculus of Constructions (CC)

Coquand and Huet (1985)

Combines ideas from:

• Martin Löf’s Type Theory
• Automath: system invented in the 60’s in which we have been able to prove real (analysis) theorems: the proof assistant “pioneer” (the type theory beneath resembles Martin Löf’s type theory).
• System F (polymorphism)

There are two sorts: Prop and Type (also denoted by $\ast$/$\square$)

Nothing really new compared to ST $λ$-calulus + dependent product, except that here, we have 4 different products, depending on which sorts we’re considering:

for $s_1, s_2 ∈ \lbrace Prop, Type \rbrace$

Example:

nat: Prop\\ true: Prop\\ Prop:Type
\cfrac{nat:Prop}{nat → nat: Prop}\\ \, \\ \cfrac{nat:Prop \qquad Prop: Type}{nat → Prop: Type} \qquad \text{(in } F_ω \text{: actually, not necessary in CC)}\\ \, \\ \cfrac{Prop: Type \qquad α: Prop \qquad α → α: Prop}{\underbrace{∀α:}_{\text{syntax-sugar for product}} Prop. α → α: Prop}\\ \, \\ \cfrac{Prop: Type}{Prop → Prop: Type}
• CC extends System F: Functions of higher-order arithmetic Propositional connectives ($∧, ∨, \ldots$)

• CC extends $λΠ$: Predicate calculus: existential quantifier, equality

• CC is a higher-order logic: in MLTT, no type of all propositions, but in CC, $\ast$ is the type of all propositions of higher-order logic

$CC_ω$: with a hierarchy of universes ($Type_1, Type_2, \ldots$)

## Calculus of Introductive Constructions (CIC)

Extends CC with universes and primitive (co-)inductive types (impredicativity allowed).

Constructive logic: if you have a proof of existence, then you have an algorithm yielding a witness.

# Datatypes

Natural numbers, rational numbers, lists, finitely branching trees, … can be encoded in Peano arithmetic (PA). But it’s tedious: one prefers a better-suited principle to construct/handle types.

## Inductive sets

Induction: examples:

• mathematical induction
• define properties/sets of objects via inference rules
• structural induction (induction on well-founded trees)

In PA, we can define subsets of $ℕ$ with inference rules: examples:

• natural numbers:

\cfrac{}{0 ∈ ℕ}\\ \, \\ \cfrac{n ∈ ℕ}{S(n) ∈ ℕ}
• even numbers $2ℕ$:

\cfrac{}{0 ∈ 2ℕ}\\ \, \\ \cfrac{n ∈ 2ℕ}{S(S(n)) ∈ 2ℕ}

Minimality: $P(0)$ and $∀n. P(n) ⇒ P(S(S(n)))$ implies $∀n ∈ 2ℕ.P(n)$

### Inductive sets as fixpoints

$ℕ$ is the smallest fixpoint of

F \, ≝ \, X ⟼ \{0\} ∪ \{S(n) \; \mid \; n ∈ X\}
• Closure by rules: $F(P) ⊆ P$
• Minimality: $∀P.F(P)⊆P ⇒ ℕ ⊆ P$

HOWEVER: Infinitely branching trees can’t be defined in PA, but they can be defined as an inductive set.

But we can’t go too far: e.g. we can’t set, to define $V$:

\cfrac{x ∈ 𝒫(V)}{C(x) ∈ V}

Because the powerset is too big. But we can do it for a family indexed by a fixed type:

\cfrac{x∈L \qquad f∈ ℕ → V}{Node(x,f) ∈ V}

Recursors are special cases of induction schemes.

## Inductive types in Coq

Inductive types: specified by introduction rules (referred to as constructors).

Coq is restrained/closed when it comes to defining new inductive types: contrary to MLTT, you can’t introduce any nex inductive type: Coq checks new inductives and accepts only those which don’t provoke any inconsistency.

Inductive nat : Type :=
| O : nat | S : nat -> nat.

or, shorter:

Inductive nat := O | S (n:nat)

By doing that, you get:

• a type $Γ ⊢ nat : \, Type$
• a set of introduction rules/constructors for this type

Pattern-matching: to clarify the type on which one matches (Coq can’t always infer it by itself):

match t as x return A(x) with O => t1 | S n => t2 end

Other examples:

Disjunction:

Inductive or (A:Prop) (B:Prop) : Prop :=
| or_introl : A -> or A B
| or_intror : B -> or A B.

Lists:

Inductive list (A:Type) : Type :=
| nil : list A
| cons : A -> list A -> list A.

Infinitely branching trees:

Inductive tree (A:Type) : Type :=
| Leaf : tree A
| Node : A -> (nat -> tree A) -> tree A.

in which case the recursor is given by:

tree_rect =
fun (A : Type) (P : tree A->Type) (f : P (Leaf A))
(f0 : forall (a : A) (t : nat -> tree A),
(forall n:nat, P (t n)) -> P (Node A a t)) =>
fix F (t : tree A) : P t :=
match t as t0 return (P t0) with
| Leaf => f
| Node y t0 => f0 y t0 (fun n : nat => F (t0 n))
end

The absurd type:

Inductive False : Prop := .

### Case analysis vs. Recursor

Recursion scheme is decomposed into two “principles” (comes from ML), separating pattern-matching and recurrence:

• Case Analysis:

λP :nat->s,
λHO : P(O),
λHS : m : nat,P(S m), λn:nat,
match n return P(n) with O=>HO |Sm=>HS m
end

of which type is:

P :nat->s,
P(O) ->
(m : nat,P(S m)) -> n : nat, P(n)

• Recursor:

λP :nat -> s,
λHO : P(O),
λHS : m : nat,P(m) -> P(S m), fixf (n:nat) : P(n) :=
match n return P(n) with O => HO |Sm => HS m(f m)
end

of which type is:

P :nat->s,
P(O) ->
(m : nat,P(m) -> P(S m)) -> n : nat, P(n)

Tags:

Updated: