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:
\[\cfrac{Γ⊢A:s_1 \qquad Γ;x:A⊢B:s_2}{Γ⊢Πx:A.B : s_2}\]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)
Leave a comment