Brendan Hart 2019-2020

\begin{code}

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

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

module PCF.Lambda.Adequacy
        (pt : propositional-truncations-exist)
        (fe : βˆ€ {𝓀 π“₯} β†’ funext 𝓀 π“₯)
        (pe : propext 𝓀₀)
       where

open PropositionalTruncation pt

open import UF.UniverseEmbedding
open import DomainTheory.Basics.Dcpo pt fe 𝓀₀
open import DomainTheory.Basics.Exponential pt fe 𝓀₀
open import DomainTheory.Basics.LeastFixedPoint pt fe 𝓀₀
open import DomainTheory.Basics.Pointed pt fe 𝓀₀
open import Lifting.Construction 𝓀₀ hiding (βŠ₯)
open import Lifting.Miscelanea 𝓀₀
open import Naturals.Properties hiding (pred-succ)
open import PCF.Combinatory.PCFCombinators pt fe 𝓀₀
open import PCF.Lambda.AbstractSyntax pt
open import PCF.Lambda.ApplicativeApproximation pt
open import PCF.Lambda.BigStep 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 PCF.Lambda.Substitution pt fe pe

open IfZeroDenotationalSemantics pe

adequate : (Οƒ : type) (d : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩) (M : PCF ⟨⟩ Οƒ) β†’ 𝓀₁ Μ‡
adequate ΞΉ        l t = πŸ™ Γ— ((p : is-defined l) β†’ t ⇓ numeral (value l p))
adequate (Οƒ β‡’ σ₁) l t = (d : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩) (M : PCF ⟨⟩ Οƒ)
                           β†’ adequate Οƒ d M
                           β†’ adequate σ₁ (pr₁ l d) (t Β· M)

lemma7-1-1 : {Οƒ : type}
           β†’ (d : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩)
           β†’ (d' : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩)
           β†’ (d' βŠ‘βŸ¨ ⟦ Οƒ ⟧ ⁻ ⟩ d)
           β†’ (M : PCF ⟨⟩ Οƒ)
           β†’ adequate Οƒ d M
           β†’ adequate Οƒ d' M
lemma7-1-1 {ΞΉ} d d' x M (_ , o) = ⋆ , f
 where
  f : (p : is-defined d') β†’ M ⇓ numeral (value d' p)
  f p = transport (Ξ» - β†’ M ⇓ numeral -) (eβ‚‚ ⁻¹) (o (=-to-is-defined e₁ p))
   where
    e₁ : d' = d
    e₁ = x p

    eβ‚‚ : value d' p = value d (=-to-is-defined e₁ p)
    eβ‚‚ = =-of-values-from-= e₁

lemma7-1-1 {Οƒ β‡’ σ₁} f g x M p = Ξ³
  where
   Ξ³ : (d : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩)
     β†’ βˆ€ N β†’ adequate Οƒ d N β†’ adequate σ₁ (pr₁ g d) (M Β· N)
   Ξ³ d N a = IH
    where
     i : adequate σ₁ (pr₁ f d) (M Β· N)
     i = p d N a

     ii : pr₁ g d βŠ‘βŸ¨ ⟦ σ₁ ⟧ ⁻ ⟩ pr₁ f d
     ii = x d

     IH : adequate σ₁ (pr₁ g d) (M Β· N)
     IH = lemma7-1-1 (pr₁ f d) (pr₁ g d) ii (M Β· N) i

adequacy-lubs : {Οƒ : type} {I : 𝓀₀ Μ‡ }
              β†’ (u : I β†’ ⟨ ⟦ Οƒ ⟧ ⁻ ⟩)
              β†’ (Ξ΄ : is-Directed ( ⟦ Οƒ ⟧ ⁻) u)
              β†’ (t : PCF ⟨⟩ Οƒ)
              β†’ ((i : I) β†’ adequate Οƒ (u i) t)
              β†’ adequate Οƒ (∐ ( ⟦ Οƒ ⟧ ⁻) Ξ΄) t
adequacy-lubs {ΞΉ} {I} u Ξ΄ t a = ⋆ , g
 where
  g : (p : is-defined (∐ ( ⟦ ι ⟧ ⁻) δ))
    β†’ t ⇓ numeral (value (∐ ( ⟦ ΞΉ ⟧ ⁻) Ξ΄) p)
  g p = βˆ₯βˆ₯-rec βˆ₯βˆ₯-is-prop f p
   where
    f : (Ξ£ i κž‰ I , is-defined (u i))
      β†’ t ⇓ numeral (value (∐ ( ⟦ ΞΉ ⟧ ⁻) Ξ΄) p)
    f (i , d) = transport (Ξ» - β†’ t ⇓ numeral -) value-lub-is-same (prβ‚‚ (a i) d)
     where
      lub-is-same : u i = ∐ ( ⟦ ι ⟧ ⁻) δ
      lub-is-same = ∐-is-upperbound ( ⟦ ι ⟧ ⁻) δ i d

      value-lub-is-same : value (u i) d = value (∐ ( ⟦ ι ⟧ ⁻) δ) p
      value-lub-is-same = =-of-values-from-= lub-is-same

adequacy-lubs {Οƒ β‡’ σ₁} {I} u Ξ΄ t a p M x = IH
 where
  ptfam : I β†’ ⟨ ⟦ σ₁ ⟧ ⁻ ⟩
  ptfam = pointwise-family ( ⟦ Οƒ ⟧ ⁻) ( ⟦ σ₁ ⟧ ⁻) u p

  ptfam-is-directed : is-Directed ( ⟦ σ₁ ⟧ ⁻) ptfam
  ptfam-is-directed = pointwise-family-is-directed ( ⟦ Οƒ ⟧ ⁻) ( ⟦ σ₁ ⟧ ⁻) u Ξ΄ p

  new_rel : (i : I) β†’ adequate σ₁ (ptfam i) (t Β· M)
  new_rel i = a i p M x

  IH : adequate σ₁ (∐ ( ⟦ σ₁ ⟧ ⁻) ptfam-is-directed) (t Β· M)
  IH = adequacy-lubs {σ₁} {I} ptfam ptfam-is-directed (t Β· M) new_rel

adequacy-step : {Οƒ : type}
                (M M' : PCF ⟨⟩ Οƒ)
              β†’ M ⊏̰ M'
              β†’ (a : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩)
              β†’ adequate Οƒ a M
              β†’ adequate Οƒ a M'
adequacy-step {ΞΉ} M M' r a (⋆ , ρ) = ⋆ , f
 where
  f : (p : is-defined a) β†’ M' ⇓ numeral (value a p)
  f p = r (value a p) (ρ p)

adequacy-step {Οƒ β‡’ σ₁} M M' r (Ο• , _) rel d M₁ x = IH
 where
  new_rel : adequate σ₁ (Ο• d) (M Β· M₁)
  new_rel = rel d M₁ x

  IH : adequate σ₁ (Ο• d) (M' Β· M₁)
  IH = adequacy-step (M Β· M₁) (M' Β· M₁) (r M₁) (Ο• d) new_rel

adequacy-bottom : {Οƒ : type}
                β†’ (t : PCF ⟨⟩ Οƒ)
                β†’ adequate Οƒ (βŠ₯ ⟦ Οƒ ⟧) t
adequacy-bottom {ΞΉ}      t = ⋆ , (Ξ» p β†’ 𝟘-elim p)
adequacy-bottom {Οƒ β‡’ σ₁} t = (Ξ» _ M _ β†’ adequacy-bottom (t Β· M))

lemma7-3 : {Οƒ : type}
         β†’ (M : PCF ⟨⟩ (Οƒ β‡’ Οƒ))
         β†’ (f : ⟨ ⟦ Οƒ β‡’ Οƒ ⟧ ⁻ ⟩)
         β†’ adequate (Οƒ β‡’ Οƒ) f M
         β†’ adequate Οƒ (pr₁ (ΞΌ ⟦ Οƒ ⟧) f) (Fix M)
lemma7-3 {Οƒ} M f rel = adequacy-lubs iter-M iter-M-is-directed (Fix M) fn
 where
  iter-M : Lift 𝓀₀ β„• β†’ ⟨ ⟦ Οƒ ⟧ ⁻ ⟩
  iter-M (n , ⋆) = iter ⟦ Οƒ ⟧ n f

  iter-M-is-directed : is-Directed (⟦ Οƒ ⟧ ⁻) iter-M
  iter-M-is-directed =
   pointwise-family-is-directed
    ((⟦ Οƒ ⟧ βŸΉα΅ˆαΆœα΅–α΅’βŠ₯ ⟦ Οƒ ⟧) ⁻) (⟦ Οƒ ⟧ ⁻)
    (iter-c' ⟦ Οƒ ⟧) (iter-is-directed' ⟦ Οƒ ⟧) f

  fn : (n : Lift 𝓀₀ β„•) β†’ adequate Οƒ (iter ⟦ Οƒ ⟧ (lower n) f) (Fix M)
  fn (zero , ⋆)   = adequacy-bottom (Fix M)
  fn (succ n , ⋆) = adequacy-step (M Β· Fix M) (Fix M) fix-⊏̰ (iter ⟦ Οƒ ⟧ (succ n) f) IH₁
   where
    IH : adequate Οƒ (iter ⟦ Οƒ ⟧ n f) (Fix M)
    IH = fn (n , ⋆)

    IH₁ : adequate Οƒ (iter ⟦ Οƒ ⟧ (succ n) f) (M Β· (Fix M))
    IH₁ = rel (iter ⟦ Οƒ ⟧ n f) (Fix M) IH

adequacy-succ : {n : β„•} {Ξ“ : Context n}
              β†’ (M : PCF Ξ“ ΞΉ)
              β†’ (d : ⟨ 【 Ξ“ 】 ⁻ ⟩)
              β†’ (f : βˆ€ {A} β†’ (x : Ξ“ βˆ‹ A) β†’ PCF ⟨⟩ A)
              β†’ adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
              β†’ adequate ΞΉ (pr₁ ⟦ Succ M βŸ§β‚‘ d) (subst f (Succ M))
adequacy-succ M d f (⋆ , rel) = ⋆ , g
 where
  g : (p : is-defined (pr₁ ⟦ Succ M βŸ§β‚‘ d))
    β†’ subst f (Succ M) ⇓ numeral (value (pr₁ ⟦ Succ M βŸ§β‚‘ d) p)
  g p = βˆ₯βˆ₯-functor (Ξ» x β†’ succ-arg x) (rel p)

pred-lemma : βˆ€ {n : β„•} {Ξ“ : Context n} {k : β„•}
           β†’ {M : PCF Ξ“ ΞΉ}
           β†’ M ⇓' numeral k
           β†’ (Pred M) ⇓' numeral (pred k)
pred-lemma {n} {Ξ“} {zero}   x = pred-zero x
pred-lemma {n} {Ξ“} {succ k} x = pred-succ x

ifzero-lemma :
  {n : β„•}
  {Ξ“ : Context n} {k : β„•}
  (M : PCF Ξ“ ΞΉ)
  (M₁ : PCF Ξ“ ΞΉ)
  (Mβ‚‚ : PCF Ξ“ ΞΉ)
  (f : βˆ€ {A} β†’ Ξ“ βˆ‹ A β†’ PCF ⟨⟩ A)
 β†’ subst f M ⇓ numeral k
 β†’ (d : ⟨ 【 Ξ“ 】 ⁻ ⟩)
   (M-is-defined : is-defined (pr₁ ⟦ M βŸ§β‚‘ d))
   (Ξ΄ : is-defined (β¦…ifZero⦆₀ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) k))
   (M₁-rel : adequate ΞΉ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (subst f M₁))
   (Mβ‚‚-rel : adequate ΞΉ (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) (subst f Mβ‚‚))
 β†’ subst f (IfZero M M₁ Mβ‚‚)
   ⇓ numeral (value (β¦…ifZero⦆₀ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) k) Ξ΄)
ifzero-lemma {n} {Ξ“} {zero} M M₁ Mβ‚‚ f x d M-is-defined Ξ΄
             (⋆ , M₁-rel) (⋆ , Mβ‚‚-rel) = Ξ³
  where
   M₁-⇓ : subst f M₁ ⇓ numeral (value (pr₁ ⟦ M₁ βŸ§β‚‘ d) Ξ΄)
   M₁-⇓ = M₁-rel Ξ΄

   Ξ³ : subst f (IfZero M M₁ Mβ‚‚)
     ⇓ numeral (value (β¦…ifZero⦆₀ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) zero) Ξ΄)
   Ξ³ = βˆ₯βˆ₯-functor (Ξ» x β†’ IfZero-zero (pr₁ x) (prβ‚‚ x)) (binary-choice x M₁-⇓)

ifzero-lemma {n} {Ξ“} {succ k} M M₁ Mβ‚‚ f x d M-is-defined Ξ΄
             (⋆ , M₁-rel) (⋆ , Mβ‚‚-rel) = Ξ³
 where
   Mβ‚‚-⇓ : subst f Mβ‚‚ ⇓ numeral (value (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) Ξ΄)
   Mβ‚‚-⇓ = Mβ‚‚-rel Ξ΄

   Ξ³ : subst f (IfZero M M₁ Mβ‚‚)
     ⇓ numeral (value (β¦…ifZero⦆₀ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) (succ k)) Ξ΄)
   Ξ³ = βˆ₯βˆ₯-functor (Ξ» x β†’ IfZero-succ (pr₁ x) (prβ‚‚ x)) (binary-choice x Mβ‚‚-⇓)

adequacy-pred : {n : β„•} {Ξ“ : Context n}
              β†’ (M : PCF Ξ“ ΞΉ)
              β†’ (d : ⟨ 【 Ξ“ 】 ⁻ ⟩)
              β†’ (f : βˆ€ {A} β†’ (x : Ξ“ βˆ‹ A) β†’ PCF ⟨⟩ A)
              β†’ adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
              β†’ adequate ΞΉ (pr₁ ⟦ Pred M βŸ§β‚‘ d) (subst f (Pred M))
adequacy-pred M d f (⋆ , rel) = ⋆ , g
 where
   g : (p : is-defined (pr₁ ⟦ Pred M βŸ§β‚‘ d))
     β†’ subst f (Pred M) ⇓ numeral (value (pr₁ ⟦ Pred M βŸ§β‚‘ d) p)
   g p = βˆ₯βˆ₯-functor pred-lemma (rel p)

adequacy-ifzero : {n : β„•} {Ξ“ : Context n}
                  (M : PCF Ξ“ ΞΉ) (M₁ : PCF Ξ“ ΞΉ) (Mβ‚‚ : PCF Ξ“ ΞΉ)
                  (d : ⟨ 【 Ξ“ 】 ⁻ ⟩)
                  (f : βˆ€ {A} β†’ (x : Ξ“ βˆ‹ A) β†’ PCF ⟨⟩ A)
                β†’ adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
                β†’ adequate ΞΉ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (subst f M₁)
                β†’ adequate ΞΉ (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) (subst f Mβ‚‚)
                β†’ adequate ΞΉ (pr₁ ⟦ IfZero M M₁ Mβ‚‚ βŸ§β‚‘ d)
                             (subst f (IfZero M M₁ Mβ‚‚))
adequacy-ifzero {n} {Ξ“} M M₁ Mβ‚‚ d f (⋆ , M-rel) M₁-rel Mβ‚‚-rel = ⋆ , g
 where
  g : (p : is-defined (pr₁ ⟦ IfZero M M₁ Mβ‚‚ βŸ§β‚‘ d))
    β†’ subst f (IfZero M M₁ Mβ‚‚) ⇓ numeral (value (pr₁ ⟦ IfZero M M₁ Mβ‚‚ βŸ§β‚‘ d) p)
  g (M-is-defined , Ξ΄) = ifzero-lemma
                          M
                          M₁
                          Mβ‚‚
                          f
                          (M-rel M-is-defined)
                          d
                          M-is-defined
                          Ξ΄
                          M₁-rel
                          Mβ‚‚-rel

lemma7-4 : {n : β„•} {Ξ“ : Context n} {Ο„ : type}
           (M : PCF Ξ“ Ο„)
           (d : ⟨ 【 Ξ“ 】 ⁻ ⟩)
           (f : βˆ€ {A} β†’ (x : Ξ“ βˆ‹ A) β†’ PCF ⟨⟩ A)
           (g : βˆ€ {A} β†’ (x : Ξ“ βˆ‹ A) β†’ adequate A (extract x d) (f x))
         β†’ adequate Ο„ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
lemma7-4 {n} {Ξ“} {.ΞΉ} Zero d f g = ⋆ , Ξ» p β†’ ∣ zero-id ∣

lemma7-4 {n} {Ξ“} {.ΞΉ} (Succ M) d f g = adequacy-succ M d f IH
 where
  IH : adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
  IH = lemma7-4 M d f g

lemma7-4 {n} {Ξ“} {.ΞΉ} (Pred M) d f g = adequacy-pred M d f IH
 where
  IH : adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
  IH = lemma7-4 M d f g

lemma7-4 {n} {Ξ“} {.ΞΉ} (IfZero M M₁ Mβ‚‚) d f g =
 adequacy-ifzero M M₁ Mβ‚‚ d f IHβ‚€ IH₁ IHβ‚‚
 where
  IHβ‚€ : adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
  IHβ‚€ = lemma7-4 M d f g

  IH₁ : adequate ΞΉ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (subst f M₁)
  IH₁ = lemma7-4 M₁ d f g

  IHβ‚‚ : adequate ΞΉ (pr₁ ⟦ Mβ‚‚ βŸ§β‚‘ d) (subst f Mβ‚‚)
  IHβ‚‚ = lemma7-4 Mβ‚‚ d f g

lemma7-4 {n} {Ξ“} {.(_ β‡’ _)} (Ζ› {n} {Ξ“} {Οƒ} {Ο„} M) d f g d₁ M₁ x = Ξ³
 where
  IH : adequate Ο„ (pr₁ ⟦ M βŸ§β‚‘ (d , d₁)) (subst (extend-with M₁ f) M)
  IH = lemma7-4 M (d , d₁) (extend-with M₁ f) extended-g
   where
    extended-g : {A : type} (x₁ : (Ξ“ ’ Οƒ) βˆ‹ A)
               β†’ adequate A (extract x₁ (d , d₁)) (extend-with M₁ f x₁)
    extended-g Z      = x
    extended-g (S x₁) = g x₁

  i : subst (extend-with M₁ f) M = subst (exts f) M [ M₁ ]
  i = subst-ext M M₁ f

  ii : subst (extend-with M₁ f) M ⊏̰ (subst f (Ζ› M) Β· M₁)
  ii = transport⁻¹ (Ξ» - β†’ - ⊏̰ (subst f (Ζ› M) Β· M₁)) i Ξ²-⊏̰

  Ξ³ : adequate Ο„ (pr₁ (pr₁ ⟦ Ζ› M βŸ§β‚‘ d) d₁) (subst f (Ζ› M) Β· M₁)
  Ξ³ = adequacy-step
       (subst (extend-with M₁ f) M)
       (subst f (Ζ› M) Β· M₁)
       ii
       (pr₁ (pr₁ ⟦ Ζ› M βŸ§β‚‘ d) d₁)
       IH

lemma7-4 (_Β·_ {n} {Ξ“} {Οƒ} {σ₁} M M₁) d f g = IHβ‚€ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (subst f M₁) IH₁
 where
  IHβ‚€ : adequate (Οƒ β‡’ σ₁) (pr₁ ⟦ M βŸ§β‚‘ d) (subst f M)
  IHβ‚€ = lemma7-4 M d f g

  IH₁ : adequate Οƒ (pr₁ ⟦ M₁ βŸ§β‚‘ d) (subst f M₁)
  IH₁ = lemma7-4 M₁ d f g

lemma7-4 {n} {Ξ“} {Οƒ} (v x) d f g = g x

lemma7-4 {n} {Ξ“} {Οƒ} (Fix M) d f g = lemma7-3 (subst f M) (pr₁ ⟦ M βŸ§β‚‘ d) IH
 where
  IH : (d₁ : ⟨ ⟦ Οƒ ⟧ ⁻ ⟩) (M₁ : PCF ⟨⟩ Οƒ)
     β†’ adequate Οƒ d₁ M₁
     β†’ adequate Οƒ (pr₁ (pr₁ ⟦ M βŸ§β‚‘ d) d₁) (subst (Ξ» {A} β†’ f) M Β· M₁)
  IH = lemma7-4 M d f g

adequacy : (M : PCF ⟨⟩ ΞΉ) (n : β„•) β†’ pr₁ ⟦ M βŸ§β‚‘ ⋆ = Ξ· n β†’ M ⇓ numeral n
adequacy M n p = prβ‚‚ iv ⋆
 where
  i : adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ ⋆) (subst ids M)
  i = lemma7-4 M ⋆ ids f
   where
    f : βˆ€ {A} β†’ (x : ⟨⟩ βˆ‹ A) β†’ adequate A (extract x ⋆) (v x)
    f x = 𝟘-elim (βˆ‹-gives-Context-is-non-empty x)

  ii : subst ids M = M
  ii = sub-id M

  iii : adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ ⋆) M
  iii = transport (adequate ΞΉ (pr₁ ⟦ M βŸ§β‚‘ ⋆)) ii i

  iv : adequate ΞΉ (Ξ· n) M
  iv = transport (Ξ» - β†’ adequate ΞΉ - M) p iii

\end{code}