---------------------------------------------------
             EXECUTING PROOFS AS COMPUTER PROGRAMS
      ---------------------------------------------------

                       Introduction  II
                       ----------------
                       
                         Chuangjie Xu

           14-16 Monday 23rd October 2017, HS B 252

          http://www.math.lmu.de/~xu/teaching/agda17/


------------------------------
    Martin-Löf type theory
------------------------------

We firstly recall the Agda definitions of MLTT types.

In Agda, types are called sets.

\begin{code}

Type : Set₁
Type = Set

\end{code}

Notice that Type has a type "Set₁".

The type of types is called a universe. Agda has a tower of universes

    Set ≡ Set₀ : Set₁ : Set₂ : ....

Π-types are primitive in Agda, and Π(x:A).P(x) is written as (x : A) → P x.

Non-dependent function types are a special case of Π-types, written as A → B.

Let's define Σ-types.

\begin{code}

infixr 5 _,_ -- mixfix operator
             -- associative to the right

data Σ {A : Type} (P : A  Type) : Type where  -- {A : Type} is an implicit argument
 _,_ : (a : A)  P a  Σ \(x : A)  P x    -- the constructor of Σ-types

pr₁ : {A : Type} {P : A  Type}
     (Σ \(x : A)  P x)  A
pr₁ (a , p) = a

pr₂ : {A : Type} {P : A  Type}
     (w : Σ \(x : A)  P x)  P (pr₁ w)
pr₂ (a , p) = p

\end{code}

Notice that the following notations are equivalent:

    Σ P   ≡   Σ \(x : A) → P x   ≡   Σ \x → P

Binary products are a special case of Σ-types.

\begin{code}

infixr 10 _×_

_×_ : Type  Type  Type
A × B = Σ \(_ : A)  B    -- treating B as a constant type family A → Type

\end{code}

Coproducts can be defined using data declaration.

\begin{code}

data _+_ (A B : Type) : Type where
 inl : A  A + B
 inr : B  A + B

case : {A B C : Type}  (A  C)  (B  C)  A + B  C
case f g (inl a) = f a
case f g (inr b) = g b

\end{code}

Empty type and unit type

\begin{code}

data 𝟘 : Type where

𝟘-elim : {A : Type}  𝟘  A
𝟘-elim ()

data 𝟙 : Type where
  : 𝟙

\end{code}

---------------------------------------
    The Curry-Howard correspondence
---------------------------------------

A proposition is true iff its corresponding type is inhabited.

                Propositions  │  Types
           ───────────────────┼───────────────────
                           ⊥  │  𝟘
                           ⊤  │  𝟙
                       P → Q  │  P → Q
                       P ∧ Q  │  P × Q
                       P ∨ Q  │  P + Q
                 ∀(x:A).P(x)  │  Π(x:A).P(x)
                 ∃(x:A).P(x)  │  Σ(x:A).P(x)
            Leibniz equality  │  identity types
        inductive predicates  │  (dependent) W-types
      coinductive predicates  │  (dependent) M-types

\begin{code}

Prop : Set₁
Prop = Type

-- A predicate P on variables of type A is Prop/Type-value function
--
--     P : A → Prop
--
-- This is also called a type family.

 : Prop
 = 𝟘

 : Prop
 = 𝟙

-- We use function types A → B to represent "A implies B".

infixr 10 _∧_
infixr 5  _∨_

_∧_ : Prop  Prop  Prop
A  B = A × B

_∨_ : Prop  Prop  Prop
A  B = A + B

-- The symbol ∀ is reserved.
-- The following notations are equivalent:
--
--   (x : A) → P x   ≡   ∀(x : A) → P x   ≡   ∀ x → P x
--
-- We're now doing logic. So I prefer to use the last one.

 : {A : Type}  (A  Prop)  Prop
 = Σ

-- Similarly to ∀, we write ∃ \x → P x instead of the others.

\end{code}

Now let's prove some simple logical axioms and rules!

0. ⊥ → A

\begin{code}

Axiom₀ : {A : Prop}
          A
Axiom₀ ()

\end{code}

1. A → A ∧ A

\begin{code}

Axiom₁ : {A : Prop}
        A  A  A
Axiom₁ a = (a , a)

\end{code}

2. A ∨ A → A

\begin{code}

Axiom₂ : {A : Prop}
        A  A  A
Axiom₂ (inl a) = a
Axiom₂ (inr a) = a

\end{code}

3. A ∧ B → B ∧ A

\begin{code}

Axiom₃ : {A B : Prop}
        A  B  B  A
Axiom₃ (a , b) = (b , a)

\end{code}

4. A ∨ B → B ∨ A

\begin{code}

Axiom₄ : {A B : Prop}
        A  B  B  A
Axiom₄ (inl a) = inr a
Axiom₄ (inr b) = inl b

\end{code}

5. (A → B) → (B → C) → A → C

\begin{code}

Axiom₅ : {A B C : Prop}
        (A  B)  (B  C)  A  C
Axiom₅ f g a = g (f a)

\end{code}

6. A → (A → B) → B

\begin{code}

Axiom₆ : {A B : Prop}
        A  (A  B)  B
Axiom₆ a f = f a

\end{code}

7. (a : A) → (∀ x → P x) → P a

\begin{code}

Axiom₇ : {A : Type} {P : A  Prop}
        (a : A)  (∀ x  P x)  P a
Axiom₇ a f = f a

\end{code}

Answers of the exercises

\begin{code}

Axiom₈ : {A B C : Prop}
        (A  B  C)  A  B  C
Axiom₈ f a b = f (a , b)

Axiom₉ : {A B C : Prop}
        (A  B)  C  A  C  B
Axiom₉ f (inl c) = inl c
Axiom₉ f (inr a) = inr (f a)

Axiom₁₀ : {A : Type} {P : A  Prop} {Q : Prop}
         (∀ x  Q  P x)  Q   x  P x
Axiom₁₀ f q x = f x q

Axiom₁₁ : {A : Type} {P : A  Prop}
         (a : A)  P a   \x  P x
Axiom₁₁ a p = (a , p)

Axiom₁₂ : {A : Type} {P : A  Prop} {Q : Prop}
         (∀ x  P x  Q)  ( \x  P x)  Q
Axiom₁₂ f (a , p) = f a p

\end{code}

----------------
    Equality
----------------

\begin{code}

data _≡_ {A : Type} (a : A) : A  Type where
 refl : a  a

sym : {A : Type} {x y : A}
     x  y  y  x
sym refl = refl

trans : {A : Type} {x y z : A}
       x  y  y  z  x  z
trans refl e = e

ap : {A B : Type} {x y : A}
    (f : A  B)  x  y  f x  f y
ap f refl = refl

transport : {A : Type} (P : A  Type) {x y : A}
           x  y  P x  P y
transport P refl p = p

\end{code}