Martin Escardo 22-24 May 2013

The MFPS paper https://doi.org/10.1016/j.entcs.2013.09.010 worked with
the combinatory version of system T. Here we work with the
lambda-calculus version. Moreover, the original version has the
iteration combinator, while here we work with the primitive recursion
combinator for system T.

\begin{code}

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

module EffectfulForcing.MFPSAndVariations.LambdaCalculusVersionOfMFPS where

open import MLTT.Spartan hiding (rec ; _^_) renaming ( to 〈〉)
open import MLTT.Fin
open import EffectfulForcing.MFPSAndVariations.Combinators
open import EffectfulForcing.MFPSAndVariations.Continuity
open import EffectfulForcing.MFPSAndVariations.Dialogue
open import EffectfulForcing.MFPSAndVariations.SystemT

\end{code}

Auxiliary interpretation of types:

\begin{code}

B〖_〗 : type  Type
B〖 ι      = B 
B〖 σ  τ  = B〖 σ   B〖 τ 

\end{code}

Generalized Kleisli extension (as in the original treatment):

\begin{code}

Kleisli-extension : {X : Type} {σ : type}  (X  B〖 σ )  B X  B〖 σ 
Kleisli-extension {X} {ι}     = kleisli-extension
Kleisli-extension {X} {σ  τ} = λ g d s  Kleisli-extension {X} {τ}  x  g x s) d

\end{code}

The interpretation of the system T constants (again as in the original
development):

\begin{code}

zero' : B 
zero' = η 0

succ' : B   B 
succ' = B-functor succ

rec' : {σ : type}  (B   B〖 σ   B〖 σ )  B〖 σ   B   B〖 σ 
rec' f x = Kleisli-extension(rec (f  η) x)

\end{code}

The auxiliary interpretation of contexts (which were not present in
the original development):

\begin{code}

B【_】 : {n : } (Γ : Cxt n)  Type
B【 Γ  = (i : Fin _)  B〖 (Γ [ i ]) 

⟪⟫ : B【 〈〉 
⟪⟫ ()

_‚‚_ : {n : } {Γ : Cxt n} {σ : type}  B【 Γ   B〖 σ   B【 Γ , σ 
(xs ‚‚ x) 𝟎       = x
(xs ‚‚ x) (suc i) = xs i

infixl 6 _‚‚_

\end{code}

The auxiliary interpretation of system TΩ terms:

\begin{code}

B⟦_⟧ : {n : } {Γ : Cxt n} {σ : type}  T' Γ σ  B【 Γ   B〖 σ 
B⟦ Ω       _ = generic
B⟦ Zero    _ = zero'
B⟦ Succ    _ = succ'
B⟦ Rec     _ = rec'
B⟦ ν i    xs = xs i
B⟦ ƛ t    xs = λ x  B⟦ t  (xs ‚‚ x)
B⟦ t · u  xs = (B⟦ t  xs) (B⟦ u  xs)

\end{code}

The dialogue tree of a closed term of type ((ι ⇒ ι) ⇒ ι):

\begin{code}

dialogue-tree : T₀ ((ι  ι)  ι)  B 
dialogue-tree t = B⟦ embed t · Ω  ⟪⟫

\end{code}

The logical relation is the same as in the original development:

\begin{code}

R : {σ : type}  (Baire   σ )  B〖 σ   Type
R {ι}     n n' = (α : Baire)  n α  decode α n'
R {σ  τ} f f' = (x  : Baire   σ )
                 (x' : B〖 σ )
                R {σ} x x'
                R {τ}  α  f α (x α)) (f' x')
\end{code}

The following lemma is again the same as in the original development,
by induction on types:

\begin{code}

R-kleisli-lemma : (σ : type)
                  (g  :   Baire   σ )
                  (g' :   B〖 σ )
                 ((k : )  R (g k) (g' k))
                 (n  : Baire  )
                  (n' : B )
                 R n n'
                 R  α  g (n α) α) (Kleisli-extension g' n')

R-kleisli-lemma ι g g' rg n n' rn = λ α 
 g (n α) α                          =⟨ rg (n α) α 
 decode α (g' (n α))                =⟨ ap  k  decode α (g' k)) (rn α) 
 decode α (g' (decode α n'))        =⟨ decode-kleisli-extension g' n' α 
 decode α (kleisli-extension g' n') 

R-kleisli-lemma (σ  τ) g g' rg n n' rn =
 λ y y' ry  R-kleisli-lemma
              τ
               k α  g k α (y α))
               k  g' k y')
               k  rg k y y' ry)
              n
              n'
              rn
\end{code}

The main lemma is a modification of the main lemma in the original
development, still by induction on terms. We don't have cases for the
combinators K and S anymore, but we need to add two cases for ν and ƛ,
and we need to modify the case for application _·_, which becomes more
difficult (in a routine way).  Additionally, we first need to extend R
to contexts (in the obvious way):

\begin{code}

Rs : {n : } {Γ : Cxt n}  (Baire   Γ )  B【 Γ   Type
Rs {n} {Γ} xs ys = (i : Fin n)  R {Γ [ i ]}  α  xs α i) (ys i)

main-lemma : {n : } {Γ : Cxt n}
             {σ : type}
             (t : T' Γ σ)
             (xs : Baire   Γ )
             (ys : B【 Γ )
            Rs xs ys
            R  α   t ⟧' α (xs α)) (B⟦ t  ys)

main-lemma Ω xs ys cr = λ n n' rn α 
 α (n α)               =⟨ ap α (rn α) 
 α (decode α n')       =⟨ generic-diagram α n' 
 decode α (generic n') 

main-lemma Zero xs ys cr = λ α  refl

main-lemma Succ xs ys cr = λ n n' rn α  
 succ (n α)          =⟨ ap succ (rn α) 
 succ (decode α n')  =⟨ decode-α-is-natural succ n' α 
 decode α (succ' n') 

main-lemma (Rec {_} {_} {σ}) _ _ _ = lemma
 where
  lemma : (f  : Baire     σ    σ )
          (f' : B   B〖 σ   B〖 σ )
         R {ι  σ  σ} f f'
         (x  : Baire   σ )
          (x' : B〖 σ )
         R {σ} x x'
         (n  : Baire  )
          (n' : B )  R {ι} n n'
         R {σ}  α  rec (f α) (x α) (n α))
                (Kleisli-extension(rec (f'  η) x') n')
  lemma f f' rf x x' rx = R-kleisli-lemma σ g g' rg
   where
    g :   Baire   σ 
    g k α = rec (f α) (x α) k

    g' :   B〖 σ 
    g' k = rec (f'  η) x' k

    rg : (k : )  R (g k) (g' k)
    rg 0        = rx
    rg (succ k) = rf  α  k) (η k)  α  refl) (g k) (g' k) (rg k)

main-lemma (ν i) xs ys cr = cr i

main-lemma {n} {Γ} {σ  τ} (ƛ t) xs ys cr = IH
 where
  IH : (x : Baire   σ )
       (y : B〖 σ )
       R x y
       R  α   t ⟧' α (xs α  x α)) (B⟦ t  (ys ‚‚ y))
  IH x y r = main-lemma t  α  xs α  x α) (ys ‚‚ y) h
    where
     h : (i : Fin (succ n))  R  α  (xs α  x α) i) ((ys ‚‚ y) i)
     h 𝟎       = r
     h (suc i) = cr i

main-lemma (t · u) xs ys cr = IH-t  α   u ⟧' α (xs α)) (B⟦ u  ys) IH-u
 where
  IH-t : (x  : Baire   _ )
         (x' : B〖 _ )
        R x x'
        R  α   t ⟧' α (xs α) (x α))
           (B⟦ t  ys x')
  IH-t = main-lemma t xs ys cr

  IH-u : R  α   u ⟧' α (xs α)) (B⟦ u  ys)
  IH-u = main-lemma u xs ys cr

\end{code}

Of course, all we are interested in is the ground case of the
main-lemma for closed terms, but we needed to prove the general case
to get that, using a logical relation to have a suitable induction
hypothesis, as usual.

\begin{code}

main-closed-ground : (t : T' 〈〉 ι) (α : Baire)
                     t ⟧' α ⟨⟩  decode α (B⟦ t  ⟪⟫)
main-closed-ground t = main-lemma t  α  ⟨⟩) ⟪⟫ (λ())

\end{code}

Then the correctness of the dialogue-tree function follows directly:

\begin{code}

dialogue-tree-correct : (t : T₀ ((ι  ι)  ι))
                        (α : Baire)
                        t ⟧₀ α  decode α (dialogue-tree t)
dialogue-tree-correct t α =
  t ⟧₀ α                       =⟨ ap  f  f ⟨⟩ α) (preservation t α) 
  embed t ⟧' α ⟨⟩ α            =⟨ main-closed-ground (embed t · Ω) α 
 decode α (B⟦ embed t · Ω  ⟪⟫) =⟨ refl 
 decode α (dialogue-tree t)     

\end{code}

And the main theorem follows directly from this:

\begin{code}

eloquence-theorem : (f : Baire  )
                   T-definable f
                   eloquent f
eloquence-theorem f (t , r) =
 (dialogue-tree t ,
  λ α  dialogue (dialogue-tree t) α =⟨ (dialogue-tree-correct t α)⁻¹ 
         t ⟧₀ α                     =⟨ ap  -  - α) r 
        f α                          )

eloquence-corollary₀ : (f : Baire  )
                      T-definable f
                      is-continuous f
eloquence-corollary₀ f d = eloquent-functions-are-continuous
                            f
                            (eloquence-theorem f d)

eloquence-corollary₁ : (f : Baire  )
                      T-definable f
                      is-uniformly-continuous (C-restriction f)
eloquence-corollary₁ f d = eloquent-functions-are-UC
                            (C-restriction f)
                            (restriction-is-eloquent f
                            (eloquence-theorem f d))
\end{code}

Examples:

\begin{code}

module examples where

 open import MLTT.Athenian using (List)
 open List

 max :     
 max 0        y        = y
 max (succ x) 0        = succ x
 max (succ x) (succ y) = succ (max x y)

 mod : List   
 mod []      = 0
 mod (x  s) = max (succ x) (mod s)

 mod-cont : T₀ ((ι  ι)  ι)  Baire  
 mod-cont t α = mod (pr₁ (eloquence-corollary₀  t ⟧₀ (t , refl) α))

 m₁ : (  )  
 m₁ = mod-cont (ƛ (ν₀ · numeral 17))

 m₁-explicitly : m₁  λ x  18
 m₁-explicitly = refl

 example₁ : m₁ id  18
 example₁ = refl

 example₁' : m₁  i  0)  18
 example₁' = refl

 m₂ : (  )  
 m₂ = mod-cont (ƛ (ν₀ · (ν₀ · numeral 17)))

 m₂-explicitly : m₂  λ α  succ (max 17 (α 17))
 m₂-explicitly = refl

 example₂ : m₂ succ  19
 example₂ = refl

 example₂' : m₂  i  0)  18
 example₂' = refl

 example₂'' : m₂ id  18
 example₂'' = refl

 example₂''' : m₂ (succ  succ)  20
 example₂''' = refl


 Add : {n : } {Γ : Cxt n}  T Γ (ι  ι  ι)
 Add = Rec · (ƛ Succ)

 t₃ : T₀ ((ι  ι)  ι)
 t₃ = ƛ (ν₀ · (ν₀ · (Add · (ν₀ · numeral 17) · (ν₀ · numeral 34))))

 add :     
 add = rec  _  succ)

 t₃-meaning :  t₃ ⟧₀  λ α  α (α (add (α 17) (α 34)))
 t₃-meaning = refl

 m₃ : (  )  
 m₃ = mod-cont t₃

 example₃ : m₃ succ  55
 example₃ = refl

 example₃' : m₃ id  52
 example₃' = refl

 example₃'' : m₃  i  0)  35
 example₃'' = refl

 example₃''' : m₃  i  300)  601
 example₃''' = refl

 example₃'''' : m₃  i  add i i)  205
 example₃'''' = refl

 f : T₀ ((ι  ι)  ι)
 f = ƛ (ν₀ · (ν₀ · (ν₀ · numeral 17)))

 m₄ : (  )  
 m₄ = mod-cont f

 example₄ : m₄ id  18
 example₄ = refl

 example₄' : m₄  i  0)  18
 example₄' = refl

 example₄'' : m₄ succ  20
 example₄'' = refl

 example₄''' : m₄  i  add i i)  69
 example₄''' = refl

 example₄'''' :  f ⟧₀  i  add i i)  136
 example₄'''' = refl

\end{code}