Brendan Hart 2019-2020

\begin{code}

{-# OPTIONS --safe --without-K --lossy-unification #-}

open import MLTT.Spartan
open import UF.FunExt
open import UF.PropTrunc
open import UF.Subsingletons

module PCF.Lambda.SubstitutionDenotational
        (pt : propositional-truncations-exist)
        (fe :  {𝓤 𝓥}  funext 𝓤 𝓥)
        (pe : propext 𝓤₀)
       where

open PropositionalTruncation pt

open import DomainTheory.Basics.Dcpo pt fe 𝓤₀
open import DomainTheory.Basics.LeastFixedPoint pt fe 𝓤₀
open import DomainTheory.Basics.Pointed pt fe 𝓤₀
open import DomainTheory.Basics.Products pt fe
open import Lifting.Monad 𝓤₀ hiding (μ)
open import Naturals.Properties
open import PCF.Combinatory.PCFCombinators pt fe 𝓤₀
open import PCF.Lambda.AbstractSyntax pt
open import PCF.Lambda.ScottModelOfContexts pt fe pe
open import PCF.Lambda.ScottModelOfTerms pt fe pe
open import PCF.Lambda.ScottModelOfTypes pt fe pe
open import UF.Base

open DcpoProductsGeneral 𝓤₀
open IfZeroDenotationalSemantics pe

replace-first-lemma : {n : } {Γ : Context n} {σ τ : type}
                      (x : (Γ  τ)  σ)
                      (d :  ( Γ  ) )
                      (T : PCF Γ τ)
                     (pr₁  v x ⟧ₑ (d , pr₁  T ⟧ₑ d))
                     pr₁  replace-first τ Γ T x ⟧ₑ d
replace-first-lemma {n} {Γ} {σ} {.σ} Z    d T = refl
replace-first-lemma {n} {Γ} {σ} {τ} (S x) d T = refl

extract-S-lemma : {n : }
                  {Γ : Context n}
                  {σ : type}
                  (d :  ( Γ  ) )
                  (e :  ( σ  ) )
                  {A : type}
                  (x : Γ  A)
                 extract x d  extract (S {n} {Γ} {A} {σ} x) (d , e)
extract-S-lemma d e Z     = refl
extract-S-lemma d e (S x) = refl

rename-lemma : {n m : }
               {Γ : Context n} {Δ : Context m}
               {σ : type}
               (M : PCF Γ σ)
               (ρ :  {A}  Γ  A  Δ  A)
               (d :  ( Δ  ) )
               (e :  ( Γ  ) )
              ({A : type} (x : Γ  A)  extract x e  extract (ρ x) d)
              pr₁  rename ρ M ⟧ₑ d  pr₁  M ⟧ₑ e
rename-lemma Zero ρ d e eq = refl
rename-lemma (Succ M) ρ d e eq = ap (𝓛̇ succ) (rename-lemma M ρ d e eq)
rename-lemma (Pred M) ρ d e eq = ap (𝓛̇ pred) (rename-lemma M ρ d e eq)
rename-lemma (IfZero M M₁ M₂) ρ d e eq =
 ap₃
  x₁ x₂ x₃  pr₁ (⦅ifZero⦆₁ x₂ x₃) x₁)
 (rename-lemma M ρ d e eq)
 (rename-lemma M₁ ρ d e eq) (rename-lemma M₂ ρ d e eq)

rename-lemma (ƛ {n} {Γ} {σ} {τ} M) ρ d e eq = γ
 where
  IH :  z  pr₁  rename (ext ρ) M ⟧ₑ (d , z))   z  pr₁  M ⟧ₑ (e , z))
  IH z = rename-lemma M (ext ρ) (d , z) (e , z) g
   where
     g :  {A}  (x : (Γ  σ)  A)  extract x (e , z)  extract (ext ρ x) (d , z)
     g Z = refl
     g (S x) = eq x

  γ : pr₁  rename ρ (ƛ M) ⟧ₑ d  pr₁  ƛ M ⟧ₑ e
  γ = to-subtype-= (being-continuous-is-prop ( σ  ) ( τ  )) (dfunext fe IH)

rename-lemma (M · M₁) ρ d e eq =
 ap₂
  pr₁
  (rename-lemma M ρ d e eq)
  (rename-lemma M₁ ρ d e eq)

rename-lemma (v x) ρ d e eq = eq x ⁻¹
rename-lemma (Fix {_} {_} {σ} M) ρ d e eq =
 ap
  (pr₁ (μ  σ ))
  (rename-lemma M ρ d e eq)

substitution-lemma : {n : }{Γ : Context n}
                     {m : }{Δ : Context m}
                     {σ : type}
                     (M : PCF Γ σ)
                     (f :  {A}  Γ  A  PCF Δ A)
                     (e :  ( Γ  ) )
                     (d :  ( Δ  ) )
                     (g :  {A}  (x : Γ  A)  pr₁  v x ⟧ₑ e  pr₁  f x ⟧ₑ d )
                    pr₁  M ⟧ₑ e  pr₁  subst f M ⟧ₑ d
substitution-lemma Zero f e d g = refl
substitution-lemma (Succ M) f e d g = ap (𝓛̇ succ) (substitution-lemma M f e d g)
substitution-lemma (Pred M) f e d g = ap (𝓛̇ pred) (substitution-lemma M f e d g)
substitution-lemma (IfZero M M₁ M₂) f e d g =
 pr₁ (⦅ifZero⦆₁ (pr₁  M₁ ⟧ₑ e) (pr₁  M₂ ⟧ₑ e)) (pr₁  M ⟧ₑ e)                        =⟨ i 
 pr₁ (⦅ifZero⦆₁ (pr₁  M₁ ⟧ₑ e) (pr₁  M₂ ⟧ₑ e)) (pr₁  subst f M ⟧ₑ d)                =⟨ ii 
 pr₁ (⦅ifZero⦆₁ (pr₁  subst f M₁ ⟧ₑ d) (pr₁  M₂ ⟧ₑ e)) (pr₁  subst f M ⟧ₑ d)        =⟨ iii 
 pr₁ (⦅ifZero⦆₁ (pr₁  subst f M₁ ⟧ₑ d) (pr₁  subst f M₂ ⟧ₑ d)) (pr₁  subst f M ⟧ₑ d) 
 where
  i = ap
      (pr₁ (⦅ifZero⦆₁ (pr₁  M₁ ⟧ₑ e) (pr₁  M₂ ⟧ₑ e)))
      (substitution-lemma M f e d g)

  ii = ap
         -  pr₁ (⦅ifZero⦆₁ - (pr₁  M₂ ⟧ₑ e)) (pr₁  subst f M ⟧ₑ d))
        (substitution-lemma M₁ f e d g)

  iii = ap
          -  pr₁ (⦅ifZero⦆₁ (pr₁  subst f M₁ ⟧ₑ d) -) (pr₁  subst f M ⟧ₑ d))
         (substitution-lemma M₂ f e d g)

substitution-lemma {_} {_} {m} {Δ} (ƛ {n} {Γ} {σ} {τ} M) f e d g = e₂
 where
   e₁ : (pr₁ (pr₁  ƛ M ⟧ₑ e))  (pr₁ (pr₁  subst f (ƛ M) ⟧ₑ d))
   e₁ x = substitution-lemma M (exts f) (e , x) (d , x) new_g
    where
     new_g : {A : type}
             (z : (Γ  σ)  A)
            pr₁  v z ⟧ₑ (e , x)  pr₁  exts f z ⟧ₑ (d , x)
     new_g     Z     = refl
     new_g {A} (S z) =
      pr₁  v (S {n} {Γ} {A} {σ} z) ⟧ₑ (e , x) =⟨ refl 
      pr₁  v z ⟧ₑ e                           =⟨  g z 
      pr₁  f z ⟧ₑ d                           =⟨ i 
      pr₁  exts f (S z) ⟧ₑ (d , x)            
       where
        i = (rename-lemma (f z) S (d , x) d  x₁  refl)) ⁻¹

   e₂ : pr₁  ƛ M ⟧ₑ e  pr₁  subst f (ƛ M) ⟧ₑ d
   e₂ = to-subtype-=
         (being-continuous-is-prop ( σ  ) ( τ  ))
         (dfunext fe e₁)

substitution-lemma (M · M₁) f e d g = γ
 where
  IH₁ : pr₁  M₁ ⟧ₑ e  pr₁  subst f M₁ ⟧ₑ d
  IH₁ = substitution-lemma M₁ f e d g
  IH : pr₁  M ⟧ₑ e  pr₁  subst f M ⟧ₑ d
  IH = substitution-lemma M f e d g

  γ = pr₁ (pr₁  M ⟧ₑ e) (pr₁  M₁ ⟧ₑ e)                               =⟨ i 
      pr₁ (pr₁  M ⟧ₑ e) (pr₁  subst f M₁ ⟧ₑ d)                       =⟨ ii 
      pr₁ (pr₁  subst  {A}  f) M ⟧ₑ d) (pr₁  subst  {A}  f) M₁ ⟧ₑ d)  
   where
    i  = ap (pr₁ (pr₁  M ⟧ₑ e)) IH₁
    ii = ap  -  pr₁ - (pr₁  subst f M₁ ⟧ₑ d)) IH

substitution-lemma {n} {Γ} {m} {Δ} (v x) f e d g = g x
substitution-lemma {n} {Γ} {m} {Δ} {σ} (Fix M) f e d g =
 ap
   -  pr₁ (μ  σ  ) -)
  (substitution-lemma M f e d g)

β-equality : {n : }
             {Γ : Context n}
             {σ τ : type}
             (E : PCF (Γ  τ) σ)
             (T : PCF Γ τ)
             (d :  ( Γ  ) )
            pr₁  (ƛ E) · T ⟧ₑ d  pr₁  E [ T ] ⟧ₑ d
β-equality {n} {Γ} {σ} {τ} E T d =
 substitution-lemma E (replace-first τ Γ T) (d , (pr₁  T ⟧ₑ d)) d g
  where
    g : {A : type}
        (x : (Γ  τ)  A)
       pr₁  v x ⟧ₑ (d , pr₁  T ⟧ₑ d)  pr₁  replace-first τ Γ T x ⟧ₑ d
    g Z     = refl
    g (S x) = refl

\end{code}