module Section1 where


-- 1. Introduction
-- ===============
--
-- 1.1. Outline of the formalisation
-- ---------------------------------
--
-- -   We formalize terms-in-context, `Γ ⊢ t ∷ A`, as a calculus of proof trees, `Γ ⊢ A`, for
--     implicational logic, i.e., term `t` is seen as a proof tree that derives `A` from the assumptions
--     contained in `Γ`.  A notion of equivalence of terms-in-context (including, e.g., β-reduction
--     and η-conversion) is then defined with a conversion relation `_≅_` on these proof trees.
--
-- -   We give a Kripke model with an ordered set of worlds and define when a proposition `A` is
--     true for a world `w` in the model, `w ⊩ A`.  We also define an extensional equality between
--     objects in the model.
--
-- -   We define an interpreter `⟦_⟧` that maps a proof tree in the theory to its semantics in the
--     Kripke model.  According to the Curry-Howard correspondence of programs to proofs
--     and types to propositions, the type of the interpreter expresses soundness of the theory of
--     proof trees with respect to the Kripke model.  Consequently, the interpreter can be seen
--     as a constructive soundness proof.
--
-- -   We also define an inversion function, `reify`, which returns a proof tre corresponding to
--     a given semantic object, yielding—again by the Curry-Howard isomorphism—a
--     completeness proof.
--
--     The inversion function is based on the principle of normalization by evaluation [3].
--     Obviously, for proof trees `M` and `N` with the same semantics, inversion yields the same proof
--     tree `reify ⟦ M ⟧ = reify ⟦ N ⟧`.  Consequently, we define a normalization function, `nf`, as
--     the composition of the interpreter and the inversion function.  We prove that if `M` is a proof
--     tree, then `M ≅ nf M`; together with the soundness result, this yields a decision algorithm
--     for convertibility.  We further show that `nf` returns a proof term in long η-normal form.
--
-- -   We prove that the convertibility relation on proof trees is sound and complete.  The proof
--     of soundness, i.e., convertible proof trees have the same semantics, is straightforward by
--     induction on the structure of the trees.  The completeness proof, i.e., if `⟦ M ⟧` and `⟦ N ⟧` are
--     equal, then `M` and `N` are convertible, uses the fact that `reify ⟦ M ⟧` is exactly the same as
--     `reify ⟦ N ⟧`, and since `M ≅ nf M ≡ reify ⟦ M ⟧` and vice versa for `N`, we get that `M ≅ N`.
--
-- -   We define a calculus of simply typed ƛterms, a typed convertibility relation on the terms,
--     and a deterministic reduction, `_⇓_`.  We also define an erasure function on proof trees that
--     maps a proof tree `M` into a well-typed term `M ⁻`.  For every well-typed term there is at
--     least one proof tree that erases to this term; for defining the semantics of well-typed terms
--     through that of proof trees, it suffices to show that all proof trees that erase to the same
--     well-typed term have the same semantics.
--
-- -   Because we know that convertible proof trees have the same semantics, it remains to
--     show that all proof trees that erase to a given well-typed term are convertible.  We use an
--     argument due to Streicher [19]: we first prove that if `nf M ⁻` and `nf N ⁻` are the same,
--     then `M ≅ N`.  Secondly, we prove that if a proof tree `M` erases to a well-typed term `t`,
--     then `t ⇓ nf M ⁻`.  Now, if two proof trees `M` and `N` erase to the same well-typed term
--     `t`, then `t ⇓ nf M ⁻` and `t ⇓ nf N ⁻`.  Since the reduction is deterministic we have that
--     `nf M ⁻` and `nf N ⁻` are the same, and hence `M ≅ N`.
--
-- -   We prove that the convertibility relation on proof trees is sound and complete, and give
--     a decision algorithm for checking convertibility of two well-typed terms.
--
-- (…)


open import Agda.Builtin.FromString public
  using (IsString ; fromString)

open import Data.Bool public
  using (Bool ; T ; true ; false ; not)
  renaming (_∧_ to and)

open import Data.Empty public
  using ()
  renaming (⊥-elim to elim⊥)

open import Data.Product public
  using (Σ ; _,_ ; _×_ ; proj₁ ; proj₂)

open import Data.Unit public
  using ( ; tt)

import Data.String as Str
open Str
  using (String)

open import Function public
  using (_∘_ ; case_of_ ; flip ; id)

open import Relation.Binary.PropositionalEquality public
  using (_≡_ ; _≢_ ; refl ; cong ; subst ; sym ; trans)
  renaming (cong₂ to cong²)

open import Relation.Nullary public
  using (¬_ ; Dec ; yes ; no)

import Relation.Nullary.Decidable as Decidable
open Decidable using (⌊_⌋) public

open import Relation.Nullary.Negation public
  renaming (contradiction to _↯_)


module _ where
  data Name : Set where
    name : String  Name

  module _ where
    inj-name :  {s s′}  name s  name s′  s  s′
    inj-name refl = refl

    _≟_ : (x x′ : Name)  Dec (x  x′)
    name s  name s′ = Decidable.map′ (cong name) inj-name (s Str.≟ s′)

    _≠_ : Name  Name  Bool
    x  x′ = not  x  x′ 

  instance
    str-Name : IsString Name
    str-Name = record
      { Constraint = λ s  
      ; fromString = λ s  name s
      }


module _ where
  record Raiseable
      {World : Set}
      (_⊩◌  : World  Set)
      {_⊒_   : World  World  Set} : Set₁ where
    field
      ↑⟨_⟩  :  {w w′}  w′  w  w ⊩◌  w′ ⊩◌
  open Raiseable {{…}} public

  record Lowerable
      {World : Set}
      (◌⊩_  : World  Set)
      {_⊒_   : World  World  Set} : Set₁ where
    field
      ↓⟨_⟩  :  {w w′}  w′  w  ◌⊩ w′  ◌⊩ w
  open Lowerable {{…}} public