Skip to content

Latest commit

 

History

History
348 lines (242 loc) · 7.97 KB

lecture2.lagda.md

File metadata and controls

348 lines (242 loc) · 7.97 KB
{-# OPTIONS --without-K --safe #-}

module lecture2 where

-- lecture 2
-- Plan: basic MLTT types, including their elimination principles.
--

open import lecture1 hiding (𝟘 ; 𝟙 ; D ; ℕ ; _+_)
open import introduction using (ℕ ; zero ; suc ; _+_)

-- empty type
data 𝟘 : Type where

-- Π x ꞉ X , A x
-- (X → B) =. Π x ꞉ X , B

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

-- 𝟘 interpreted as "false"

¬_ : Type  Type
¬ A = A  𝟘

infix 1000 ¬_

𝟘-nondep-elim : {B : Type}  𝟘  B
𝟘-nondep-elim {B} = 𝟘-elim {λ _  B}

-- A := λ _ → B


is-empty : Type  Type
is-empty A = A  𝟘

-- A ≡ 𝟘 or A ≃ 𝟘.

𝟘-is-empty'' : is-empty 𝟘
𝟘-is-empty'' = λ ()

𝟘-is-empty : is-empty 𝟘
𝟘-is-empty = 𝟘-nondep-elim

𝟘-is-empty' : is-empty 𝟘
𝟘-is-empty' = id

-- Unit type:

-- Record definitions satisfy a certain "η" rule.

record 𝟙 : Type where
 constructoropen 𝟙 public

𝟙-is-nonempty' : ¬ is-empty 𝟙
𝟙-is-nonempty' = λ (f : 𝟙  𝟘)  f ⋆

𝟙-is-nonempty : ¬ is-empty 𝟙
𝟙-is-nonempty f = f ⋆

𝟙-elim : {A : 𝟙  Type}
        A ⋆
        (x : 𝟙)  A x
𝟙-elim a x = a

𝟙-nondep-elim : {A : Type}
               A
               𝟙  A
𝟙-nondep-elim {A} = 𝟙-elim {λ _  A}

-- Type of binary digits:

data 𝟚 : Type where
 𝟎 𝟏 : 𝟚

𝟚-elim : {A : 𝟚  Type}
        A 𝟎
        A 𝟏
        (x : 𝟚)  A x
𝟚-elim a₀ a₁ 𝟎 = a₀
𝟚-elim a₀ a₁ 𝟏 = a₁

𝟚-nondep-elim : {A : Type}
               A
               A
               𝟚  A
𝟚-nondep-elim {A} = 𝟚-elim {λ _  A}

-- Π types in Agda are primitive.
--
-- We have that Π x ꞉ X , A x is written
--
--              (x : X) → A x,   or
--              ∀ (x : X) → A x, or
--              ∀ x → A x        (if Agda can infer X).
--
-- We can introduce Π-syntax if we wish:

Pi : (A : Type) (B : A  Type)  Type
Pi A B = (x : A)  B x

syntax Pi A (λ x  b) = Π x ꞉ A , b
--                          ↑
--                         this is typed "\:4" in emacs mode and is not the same as ":".
--                         (we can't use the normal one unfortunately.)


-- Function composition.

-- The usual one found in mathematics:

module _ where
 private
  _∘_ : {A B C : Type}  (B  C)  (A  B)  (A  C)
  (g ∘ f) x = g (f x)

-- A more general version:

_∘_ : {A B : Type} {C : B  Type}
     ((y : B)  C y)
     (f : A  B)
     (x : A)  C (f x)
(g ∘ f) x = g (f x)

-- The types-as-mathematical-statements reading of dependent function composition is:
--
-- If (for all y : B we have that C y) and f : A → B is any function, then
-- for all x : A we have that C (f x).
--
-- The proof is function composition.


-- Σ-types:

module _ where
 private

  data Σ {A : Type } (B : A  Type) : Type  where
   _,_ : (x : A) (y : B x)  Σ {A} B

  pr₁ : {A : Type} {B : A  Type}  Σ B  A
  pr₁ (x , y) = x

  pr₂ : {A : Type} {B : A  Type}  (z : Σ B)  B (pr₁ z)
  pr₂ (x , y) = y

-- Our preferred definition:

record Σ {A : Type } (B : A  Type) : Type  where
 constructor
  _,_
 field
  pr₁ : A
  pr₂ : B pr₁

open Σ public
infixr 0 _,_

pr₁-again : {A : Type} {B : A  Type}  Σ B  A
pr₁-again = pr₁

pr₂-again : {A : Type} {B : A  Type} ((x , y) : Σ B)  B x
pr₂-again = pr₂


-- This satisfies the η-rule z = (pr₁ z , pr₂ z), which the definition using `data` doesn't.


Sigma : (A : Type) (B : A  Type)  Type
Sigma A B = Σ {A} B

syntax Sigma A (λ x  b) = Σ x ꞉ A , b

infix -1 Sigma

-- Recall that we defined D as follows in the first lecture:

D : Bool  Type
D true  = ℕ
D false = Bool

-- Example

Σ-example₁ Σ-example₂ : Σ b ꞉ Bool , D b
Σ-example₁ = (true  , 17)
Σ-example₂ = (false , true)

-- Σ-elim is "curry":

Σ-elim : {A : Type } {B : A  Type} {C : (Σ x ꞉ A , B x)  Type}
        ((x : A) (y : B x)  C (x , y))
        (z : Σ x ꞉ A , B x)  C z
Σ-elim f (x , y) = f x y

Σ-uncurry : {A : Type } {B : A  Type} {C : (Σ x ꞉ A , B x)  Type}
           ((z : Σ x ꞉ A , B x)  C z)
           (x : A) (y : B x)  C (x , y)
Σ-uncurry g x y = g (x , y)

_×_ : Type  Type  Type
A × B = Σ x ꞉ A , B

-- (x : X) → A x
-- (x : X) × A x

infixr 2 _×_

-- We will have that A₀ × A₁ ≅ Π (n : 𝟚) , A n ≅ ((n : 𝟚) → A n)
-- where A 𝟎 = A₀
--       A 𝟏 = A₁
--       A : 𝟚 → Type
-- f ↦ (f 𝟎 , f 𝟏)
-- (a₀ , a₁) ↦ 𝟚-elim a₀ a₁
-- But we need function extensionality to prove that this works.
-- Binary products are special cases of products.

Various uses of Σ:

-- Binary sums _+_ ∔

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

-- Mathematically A ∔ B is (disjoint) union.
-- Logically, it is "or" (disjunction).
-- ∥ A ∔ B ∥.

infixr 20 _∔_

∔-elim : {A B : Type} (C : A ∔ B  Type)
        ((x : A)  C (inl x)) -- f
        ((y : B)  C (inr y)) -- g
        (z : A ∔ B)  C z
∔-elim C f g (inl x) = f x
∔-elim C f g (inr y) = g y

∔-nondep-elim : {A B C : Type}
               (A  C)
               (B  C)
               (A ∔ B  C)
∔-nondep-elim {A} {B} {C} = ∔-elim (λ z  C)

-- We will have that A₀ ∔ A₁ ≅ Σ (n : 𝟚) , A n
-- where A 𝟎 = A₀
--       A 𝟏 = A₁
-- inl a₀ ↦ (𝟎 , a₀)
-- inr a₁ ↦ (𝟏 , a₁)
-- Binary sums are special cases of sums.


-- We call an element of the identity type x ≡ y an
-- "identification". The terminology "path" is also used.
-- I prefer the former.

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

-- refl x : proof that x is equal to itself.

infix 0 _≡_

-- The following is also called "J":

≡-elim : {X : Type} (A : (x y : X)  x ≡ y  Type)
        ((x : X)  A x x (refl x))
        (x y : X) (p : x ≡ y)  A x y p
≡-elim A f x x (refl x) = f x

-- To conclude that a property A x y p of identifications p of
-- elements x and y holds for all x, y and p, it is enough to show
-- that A x x (refl x) holds for all x.

≡-nondep-elim : {X : Type} (A : X  X  Type)
               ((x : X)  A x x)
               (x y : X)  x ≡ y  A x y
≡-nondep-elim A = ≡-elim (λ x y _  A x y)

-- We finished lecture 2 here. So we'll start lecture 3 here.

trans : {A : Type} {x y z : A}  x ≡ y  y ≡ z  x ≡ z
trans p (refl y) = p

sym : {A : Type} {x y : A}  x ≡ y  y ≡ x
sym (refl x) = refl x

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

ap₂ : {A B C : Type} (f : A  B  C) {x x' : A} {y y' : B}
     x ≡ x'  y ≡ y'  f x y ≡ f x' y'
ap₂ f (refl x) (refl y) = refl (f x y)

transport : {X : Type} (A : X  Type)
           {x y : X}  x ≡ y  A x  A y
transport A (refl x) a = a

_∙_ : {A : Type} {x y z : A}  x ≡ y  y ≡ z  x ≡ z
_∙_ = trans

infixl 7 _∙_

_⁻¹ : {A : Type} {x y : A}  x ≡ y  y ≡ x
_⁻¹ = sym

infix  40 _⁻¹

_≤_ : Type
0     ≤ y     = 𝟙
suc x ≤ 0     = 𝟘
suc x ≤ suc y = x ≤ y

_≥_ : Type
x ≥ y = y ≤ x

_*_ :0     * y = 0
suc x * y = x * y + y

infixr 30 _*_

_divides_ : Type
x divides y = Σ z ꞉ ℕ , x * z ≡ y

is-prime : Type
is-prime p = (p ≥ 2) × ((n : ℕ)  n divides p  (n ≡ 1) ∔ (n ≡ p))


twin-prime-conjecture : Type
twin-prime-conjecture = (n : ℕ)  Σ p ꞉ ℕ , (p ≥ n)
                                          × is-prime p
                                          × is-prime (p + 2)

there-are-infinitely-many-primes : Type
there-are-infinitely-many-primes = (n : ℕ)  Σ p ꞉ ℕ , (p ≥ n) × is-prime p