Brendan Hart 2019-2020

\begin{code}

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

open import MLTT.Spartan
open import UF.PropTrunc

module PCF.Lambda.ApplicativeApproximation
        (pt : propositional-truncations-exist)
       where

open PropositionalTruncation pt

open import PCF.Lambda.AbstractSyntax pt
open import PCF.Lambda.BigStep pt

_⊏̰_ : {σ : type}  PCF ⟨⟩ σ  PCF ⟨⟩ σ  𝓤₀ ̇
_⊏̰_ {ι}      M N = (n : )  M  numeral n  N  numeral n
_⊏̰_ {σ  σ₁} M N = (P : PCF ⟨⟩ σ)  (M · P) ⊏̰ (N · P)

⊏̰-reflexive : {σ : type}  (M : PCF ⟨⟩ σ)  M ⊏̰ M
⊏̰-reflexive {ι}      M = λ n x  x
⊏̰-reflexive {σ  σ₁} M = λ P  ⊏̰-reflexive (M · P)

⊏̰-transitive : {σ : type} {M N L : PCF ⟨⟩ σ}  M ⊏̰ N  N ⊏̰ L  M ⊏̰ L
⊏̰-transitive {ι} {M} {N} {L} p₁ p₂ n step = γ
 where
  γ : L  numeral n
  γ = p₂ n (p₁ n step)

⊏̰-transitive {σ  σ₁} {M} {N} {L} p₁ p₂ P = γ
 where
  γ : (M · P) ⊏̰ (L · P)
  γ = ⊏̰-transitive (p₁ P) (p₂ P)

⊏̰-lemma : {σ : type} (M M' : PCF ⟨⟩ σ)
         ((V : PCF ⟨⟩ σ)  M ⇓' V  M' ⇓' V)
         M ⊏̰ M'
⊏̰-lemma {ι}     M M' f n x = ∥∥-functor  x₁  f (numeral n) x₁) x
⊏̰-lemma {σ  τ} M M' f P   = ⊏̰-lemma (M · P) (M' · P) γ
 where
  γ : (V : PCF ⟨⟩ τ)  (M · P) ⇓' V  (M' · P) ⇓' V
  γ V (·-step {_} {_} {_} {_} {_} {E} x x₁) = ·-step M'-step x₁
   where
    M'-step : M' ⇓' ƛ E
    M'-step = f (ƛ E) x

β-⊏̰ : {σ τ : type} {M : PCF (⟨⟩  σ) τ} {N : PCF ⟨⟩ σ}
     (M [ N ]) ⊏̰ (ƛ M · N)
β-⊏̰ {σ} {τ} {M} {N} = ⊏̰-lemma (M [ N ]) (ƛ M · N)  V x  ·-step ƛ-id x)

fix-⊏̰ : {σ : type} {M : PCF ⟨⟩ (σ  σ)}  (M · (Fix M)) ⊏̰ (Fix M)
fix-⊏̰ {σ} {M} = ⊏̰-lemma (M · Fix M) (Fix M)  V x  Fix-step x)

\end{code}