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}