Chuangjie Xu, 2015

\begin{code}

{-# OPTIONS --without-K #-}

module Preliminaries where

open import Agda.Primitive using (Level ; lzero ; lsuc ; _⊔_)

\end{code}

Identity function and function composition

\begin{code}

id : {i : Level}{X : Set i}  X  X
id x = x

infixr 30 _∘_ 

_∘_ : {i j k : Level}{X : Set i}{Y : X  Set j}{Z : (x : X)  Y x  Set k} 
      ({x : X}  (y : Y x)  Z x y)  (f : (x : X)  Y x) 
      (x : X)  Z x (f x)
g  f = λ x  g(f x)

\end{code}

Universe polymorphic sigma type

\begin{code}

infixr 3 _,_

record Σ {i j : Level} {A : Set i} (B : A  Set j) : Set (i  j) where
  constructor _,_
  field
   pr₁ : A
   pr₂ : B pr₁

open Σ public

\end{code}

Cartesian products

\begin{code}

infixr 20 _×_

_×_ : {i j : Level}  Set i  Set j  Set(i  j)
X × Y = Σ \(x : X)  Y

\end{code}

Disjoint union

\begin{code}

infixr 20 _+_

data _+_ (X₀ X₁ : Set) : Set where
  inl : X₀  X₀ + X₁
  inr : X₁  X₀ + X₁

case : {X₀ X₁ Y : Set}  (X₀  Y)  (X₁  Y)  X₀ + X₁  Y
case f₀ f₁ (inl x₀) = f₀ x₀
case f₀ f₁ (inr x₁) = f₁ x₁

cases : {X₀ X₁ Y₀ Y₁ : Set}  (X₀  Y₀)  (X₁  Y₁)  X₀ + X₁  Y₀ + Y₁
cases f₀ f₁ (inl x₀) = inl (f₀ x₀)
cases f₀ f₁ (inr x₁) = inr (f₁ x₁)

\end{code}

Empty type:

\begin{code}

data  : Set where

∅-elim : {i : Level}{A : Set i}    A
∅-elim ()

¬ : {i : Level}  Set i  Set i
¬ X = X  

\end{code}

Identity type and related lemmas:

\begin{code}

infix  30 _≡_
infixr 40 _·_
infixl 50 _⁻¹

data _≡_ {i : Level} {A : Set i} : A  A  Set i where
  refl : {a : A}  a  a

J : {i j : Level} {A : Set i} (C : (a b : A)  a  b  Set j)
   ((a : A)  C a a refl)
   (a b : A)  (p : a  b)  C a b p
J C c a .a refl = c a

_⁻¹ : {i : Level}{A : Set i}  {x y : A}  x  y  y  x
refl ⁻¹ = refl

_·_ : {i : Level}{A : Set i}  {x y z : A}  x  y  y  z  x  z
refl · refl = refl

sym-is-inverse : {X : Set} {x y : X} (p : x  y)  refl  p ⁻¹ · p
sym-is-inverse refl = refl

transport : {i j : Level}{X : Set i}{x x' : X}  (Y : X  Set j)  x  x'  Y x  Y x'
transport Y refl y = y

ap : {i j : Level}{X : Set i}{Y : Set j}  ∀(f : X  Y)  {x₀ x₁ : X}  x₀  x₁  f x₀  f x₁
ap f refl = refl

pair⁼ : {i j : Level}{X : Set i}{Y : X  Set j}{x x' : X}{y : Y x}{y' : Y x'}
       (p : x  x')  transport Y p y  y'  (x , y)  (x' , y')
pair⁼ refl refl = refl

\end{code}

Propositions and sets

\begin{code}

hprop : Set  Set
hprop X = (x y : X)  x  y

hset : Set  Set
hset X = {x y : X}  hprop (x  y)

\end{code}

Decidability and discreteness

\begin{code}

decidable : Set  Set
decidable A = A + ¬ A

discrete : Set  Set
discrete A = ∀(a a' : A)  decidable (a  a')

\end{code}

Constancy

\begin{code}

constant : {i j : Level} {X : Set i} {Y : Set j}  (X  Y)  Set(i  j)
constant f =  x x'  f x  f x'

\end{code}

Natural numbers and booleans

\begin{code}

data  : Set where 
  zero : 
  succ :   
{-# BUILTIN NATURAL  #-}

pred :   
pred 0 = 0
pred (succ n) = n

succ-injective : ∀{i j : }  succ i  succ j  i  j
succ-injective = ap pred

ℕ-discrete : discrete 
ℕ-discrete  0        0       = inl refl
ℕ-discrete  0       (succ m) = inr  ())
ℕ-discrete (succ n)  0       = inr  ())
ℕ-discrete (succ n) (succ m) = step (ℕ-discrete n m)
 where 
  step : decidable(n  m)  decidable (succ n  succ m) 
  step (inl r) = inl (ap succ r)
  step (inr f) = inr  s  f (succ-injective s))

data  : Set where
  : 
  : 
{-# BUILTIN BOOL  #-}

₂-discrete : discrete 
₂-discrete   = inl refl 
₂-discrete   = inr  ())
₂-discrete   = inr  ())
₂-discrete   = inl refl

Lemma[b≡₀∨b≡₁] : ∀{b : }  (b  ) + (b  )
Lemma[b≡₀∨b≡₁] {} = inl refl
Lemma[b≡₀∨b≡₁] {} = inr refl

Lemma[b≠₀→b≡₁] : {b : }  ¬ (b  )  b  
Lemma[b≠₀→b≡₁] {} f = ∅-elim (f refl)
Lemma[b≠₀→b≡₁] {} f = refl

Lemma[b≠₁→b≡₀] : {b : }  ¬ (b  )  b  
Lemma[b≠₁→b≡₀] {} f = refl
Lemma[b≠₁→b≡₀] {} f = ∅-elim (f refl)

\end{code}

Less-than relation

\begin{code}

infix 30 _≤_
infix 30 _<_

data _≤_ :     Set where
 ≤-zero : ∀{n : }  0  n
 ≤-succ : ∀{m n : }  m  n  succ m  succ n

_<_ :     Set
m < n = succ m  n

≤-refl : {n : }  n  n
≤-refl {0}      = ≤-zero
≤-refl {succ n} = ≤-succ ≤-refl

≤-trans : {a b c : }  a  b  b  c  a  c
≤-trans ≤-zero     v          = ≤-zero
≤-trans (≤-succ u) (≤-succ v) = ≤-succ (≤-trans u v)

≤-r-succ : {n m : }  n  m  n  succ m
≤-r-succ ≤-zero     = ≤-zero
≤-r-succ (≤-succ r) = ≤-succ (≤-r-succ r)

Lemma[n≤m+1→n≤m∨n≡m+1] : {n m : }  n  succ m  (n  m) + (n  succ m)
Lemma[n≤m+1→n≤m∨n≡m+1] {0}      {m}      r = inl ≤-zero
Lemma[n≤m+1→n≤m∨n≡m+1] {succ 0} {0}      r = inr refl
Lemma[n≤m+1→n≤m∨n≡m+1] {succ (succ n)} {0} (≤-succ ())
Lemma[n≤m+1→n≤m∨n≡m+1] {succ n} {succ m} (≤-succ r) = cases c₀ c₁ IH
 where
  c₀ : n  m  succ n  succ m
  c₀ = ≤-succ
  c₁ : n  succ m  succ n  succ (succ m)
  c₁ = ap succ
  IH : (n  m) + (n  succ m)
  IH = Lemma[n≤m+1→n≤m∨n≡m+1] {n} {m} r

Lemma[n≰m→m<n] : {n m : }  ¬(n  m)  m < n
Lemma[n≰m→m<n] {0}      {m}      f = ∅-elim (f ≤-zero)
Lemma[n≰m→m<n] {succ n} {0}      f = ≤-succ ≤-zero
Lemma[n≰m→m<n] {succ n} {succ m} f = ≤-succ (Lemma[n≰m→m<n] (f  ≤-succ))

Lemma[m≤n∧n≤m→m=n] : ∀{m n : }  m  n  n  m  m  n
Lemma[m≤n∧n≤m→m=n] {0}      {0}      ≤-zero     ≤-zero      = refl
Lemma[m≤n∧n≤m→m=n] {0}      {succ n} ≤-zero     ()
Lemma[m≤n∧n≤m→m=n] {succ m} {0}      ()         ≤-zero
Lemma[m≤n∧n≤m→m=n] {succ m} {succ n} (≤-succ r) (≤-succ r') = ap succ (Lemma[m≤n∧n≤m→m=n] r r')

\end{code}

Primitive and course-of-value inductions

\begin{code}

primitive-induction : {P :   Set}
                     P 0  (∀ n  P n  P(succ n))   n  P n
primitive-induction base step 0        = base
primitive-induction base step (succ n) = step n (primitive-induction base step n)

CoV-induction : {P :   Set}
               (∀ n  (∀ m  m < n  P m)  P n)   n  P n
CoV-induction {P} step n = step n (claim n)
 where
  Q :   Set
  Q n =  m  succ m  n  P m
  qbase : Q 0
       -- ∀ m → succ m ≤ 0 → P m
  qbase m ()
  qstep :  n  Q n  Q(succ n)
       -- ∀ n → (∀ m → succ m ≤ n → P m) → ∀ m → succ m ≤ succ n → P m
  qstep n qn m (≤-succ r) = step m  k u  qn k (≤-trans u r))
  claim :  n  Q n
       -- ∀ n → ∀ m → succ m ≤ n → P m
  claim = primitive-induction qbase qstep

\end{code}

Binary sequences

\begin{code}

₂ℕ : Set
₂ℕ =   

 : ₂ℕ
 i = 
 : ₂ℕ
 i = 

infixr 50 _∷_

data ₂Fin :   Set where
 ⟨⟩ : ₂Fin 0
 _∷_ : {n : }    ₂Fin n  ₂Fin (succ n)

take : (m : )  ₂ℕ  ₂Fin m
take 0 α = ⟨⟩
take (succ n) α = α 0  take n (α  succ)

drop :   ₂ℕ  ₂ℕ
drop 0 α = α
drop (succ m) α = drop m (α  succ)

cons : {m : }  ₂Fin m  ₂ℕ  ₂ℕ
cons ⟨⟩      α          = α 
cons (h  _) α 0        = h
cons (_  t) α (succ i) = cons t α i

Lemma[₂Fin-decidability] : (n : )  (Y : ₂Fin n  Set)
                          (∀ s  decidable (Y s))  decidable (∀ s  Y s)
Lemma[₂Fin-decidability] 0 Y decY = cases c₀ c₁ (decY ⟨⟩)
 where
  c₀ : Y ⟨⟩   s  Y s
  c₀ y ⟨⟩ = y
  c₁ : ¬ (Y ⟨⟩)  ¬ (∀ s  Y s)
  c₁ f g = f (g ⟨⟩) 
Lemma[₂Fin-decidability] (succ n) Y decY = case c₀ c₁ IH₀
 where
  Y₀ : ₂Fin n  Set
  Y₀ s = Y (  s)
  decY₀ :  s  decidable (Y₀ s)
  decY₀ s = decY (  s)
  IH₀ : decidable (∀ s  Y₀ s)
  IH₀ = Lemma[₂Fin-decidability] n Y₀ decY₀
  Y₁ : ₂Fin n  Set
  Y₁ s = Y (  s)
  decY₁ :  s  decidable (Y₁ s)
  decY₁ s = decY (  s)
  IH₁ : decidable (∀ s  Y₁ s)
  IH₁ = Lemma[₂Fin-decidability] n Y₁ decY₁
  c₀ : (∀ s  Y₀ s)  decidable (∀ s  Y s)
  c₀ y₀ = cases sc₀ sc₁ IH₁
   where
    sc₀ : (∀ s  Y₁ s)   s  Y s
    sc₀ y₁ (  s) = y₀ s
    sc₀ y₁ (  s) = y₁ s
    sc₁ : ¬ (∀ s  Y₁ s)  ¬ (∀ s  Y s)
    sc₁ f₁ ys = f₁  s  ys (  s))
  c₁ : ¬ (∀ s  Y₀ s)  decidable (∀ s  Y s)
  c₁ f₀ = inr  ys  f₀  s  ys (  s)))

\end{code}

"Agree with" relation over infinite sequences, which is an equivalence
relation and a deciable type:

\begin{code}

infixl 10 _≡[_]_

data _≡[_]_ {X : Set} : (  X)    (  X)  Set where
 ≡[zero] : {α β :   X}  α ≡[ 0 ] β
 ≡[succ] : {α β :   X}{n : }  α ≡[ n ] β  α n  β n  α ≡[ succ n ] β

≡[]-sym : {n : }{α β : ₂ℕ}  α ≡[ n ] β  β ≡[ n ] α
≡[]-sym {0}      ≡[zero]        = ≡[zero]
≡[]-sym {succ n} (≡[succ] en e) = ≡[succ] (≡[]-sym en) (e ⁻¹)

≡[]-trans : {n : }{α₀ α₁ α₂ : ₂ℕ}  α₀ ≡[ n ] α₁  α₁ ≡[ n ] α₂  α₀ ≡[ n ] α₂
≡[]-trans {0}      ≡[zero]        ≡[zero]          = ≡[zero]
≡[]-trans {succ n} (≡[succ] en e) (≡[succ] en' e') = ≡[succ] (≡[]-trans en en') (e · e')

Lemma[≡[]-cons-take] : {α β : ₂ℕ}  ∀(n : )  α ≡[ n ] cons (take n α) β
Lemma[≡[]-cons-take] {α} {β} n = lemma₁ n n ≤-refl
 where
  lemma₀ : ∀(α β : ₂ℕ)(m k : )  succ m  k  α m  cons (take k α) β m
  lemma₀ α β m        0        ()
  lemma₀ α β 0        (succ k) r          = refl
  lemma₀ α β (succ m) (succ k) (≤-succ r) = lemma₀ (α  succ) β m k r
  lemma₁ : ∀(m k : )  m  k  α ≡[ m ] cons (take k α) β
  lemma₁ 0        k        ≤-zero     = ≡[zero]
  lemma₁ (succ m) 0        ()
  lemma₁ (succ m) (succ k) (≤-succ r) = ≡[succ] (lemma₁ m (succ k) (≤-r-succ r))
                                                (lemma₀ α β m (succ k) (≤-succ r))

Lemma[≡[]-≡[]-take] : {α β γ : ₂ℕ}  ∀(n : )  α ≡[ n ] β  β ≡[ n ] cons (take n α) γ
Lemma[≡[]-≡[]-take] n en = ≡[]-trans (≡[]-sym en) (Lemma[≡[]-cons-take] n)

Lemma[cons-take-0] : {α β : ₂ℕ}  ∀(n : )  β 0  cons (take n α) β n
Lemma[cons-take-0]  0       = refl
Lemma[cons-take-0] (succ n) = Lemma[cons-take-0] n

Lemma[cons-≡[]-≤] : {n m : }{α β : ₂ℕ}  (s : ₂Fin n)  m  n  cons s α ≡[ m ] cons s β
Lemma[cons-≡[]-≤] _ ≤-zero     = ≡[zero]
Lemma[cons-≡[]-≤] s (≤-succ r) = ≡[succ] (Lemma[cons-≡[]-≤] s (≤-r-succ r)) (lemma s r)
 where
  lemma : {n m : }{α β : ₂ℕ}  (s : ₂Fin (succ n))  m  n  cons s α m  cons s β m
  lemma (b  s) ≤-zero     = refl
  lemma (b  s) (≤-succ r) = lemma s r

\end{code}

The type of function extensionality

\begin{code}

Funext : Set₁
Funext = {X : Set} {Y : X  Set} {f g : (x : X)  Y x}
        (∀(x : X)  f x  g x)  f  g

\end{code}