======================================
 =                                    =
 =  Example: lifting to higher types  =
 =                                    =
 ======================================

    Chuangjie Xu, July 2019

\begin{code}

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

open import Preliminaries
open import Tplus

\end{code}

■ A nucleus for lifting to higher types

\begin{code}

module Lifting (X : Ty) where

J : Ty  Ty
J σ = X  σ

η : {Γ : Cxt} {σ : Ty}  T Γ (σ  J σ)
η = Lam (Lam ν₁)

κ : {Γ : Cxt} {σ τ : Ty}  T Γ ((σ  J τ)  J σ  J τ)
κ = Lam (Lam (Lam (ν₂ · (ν₁ · ν₀) · ν₀)))

\end{code}

■ Relating terms and their lifting

\begin{code}

open import GentzenTranslation J η κ public

R : {ρ : Ty}   X ⟧ʸ    ρ ⟩ᴶ ⟧ʸ   ρ ⟧ʸ  Set
R {ι    } x  φ       n      = n  φ x
R {σ  τ} x (α , β) (a , b) = R x α a × R x β b
R {σ  τ} x  φ      (inl a) = case  α  R x α a)  _  𝟘) (φ x)
R {σ  τ} x  φ      (inr b) = case  _  𝟘)  β  R x β b) (φ x)
R {σ  τ} x  φ       f      = {α :   σ ⟩ᴶ ⟧ʸ} {a :  σ ⟧ʸ}  R x α a  R x (φ α) (f a)

--
-- The Kleisli extension for the base type preserves R.
--
R[KEᶥ] : (ρ : Ty) {Γ : Cxt} {γ :  Γ ⟧ˣ} (x :  X ⟧ʸ)
        {f :     ρ ⟩ᴶ ⟧ʸ} {g :    ρ ⟧ʸ}
        ((i : )  R x (f i) (g i))
        R x ( KE ρ ⟧ᵐ γ f) g

--
-- The Kleisli extension for coproducts preserves R.
--
R[KE⁺] : (ρ : Ty) (x :  X ⟧ʸ) {σ τ : Ty} {Γ : Cxt} {γ :  Γ ⟧ˣ}
        (φ :   σ ⟩ᴶ ⟧ʸ +   τ ⟩ᴶ ⟧ʸ    ρ ⟩ᴶ ⟧ʸ) (f :  σ ⟧ʸ +  τ ⟧ʸ   ρ ⟧ʸ)
        ({α :   σ ⟩ᴶ ⟧ʸ} {a :  σ ⟧ʸ}  R x α a  R x (φ (inl α)) (f (inl a)))
        ({β :   τ ⟩ᴶ ⟧ʸ} {b :  τ ⟧ʸ}  R x β b  R x (φ (inr β)) (f (inr b)))
        R x ( KE ρ ⟧ᵐ γ φ) f

--
-- Extending R to contexts
--
 : {Γ : Cxt}   X ⟧ʸ    Γ ⟫ᴶ ⟧ˣ   Γ ⟧ˣ  Set
 {ε}     _  _       _      = 𝟙
 {Γ  ρ} x (γ , a) (ξ , b) =  x γ ξ × R x a b

--
-- Variables in related contexts are related.
--
R[Var] : {Γ : Cxt} {ρ : Ty} {γ :   Γ ⟫ᴶ ⟧ˣ} {ξ :  Γ ⟧ˣ} (x :  X ⟧ʸ)
         x γ ξ  (i :  ρ  Γ )  R x (γ   i ⟩ᵛ ) (ξ  i )
R[Var] x (_ , θ)  zero    = θ
R[Var] x (ζ , _) (succ i) = R[Var] x ζ i

--
-- Any T term is related to its translation.
--
Lemma[R] : {Γ : Cxt} {ρ : Ty} (t : T Γ ρ) (x :  X ⟧ʸ)
          {γ :   Γ ⟫ᴶ ⟧ˣ} {ξ :  Γ ⟧ˣ}   x γ ξ
          R x ( t  ⟧ᵐ γ) ( t ⟧ᵐ ξ)
Lemma[R] (Var i) x ζ = R[Var] x ζ i
Lemma[R] (Lam t) x ζ = λ χ  Lemma[R] t x (ζ , χ)
Lemma[R] (f · a) x ζ = Lemma[R] f x ζ (Lemma[R] a x ζ)
Lemma[R] Zero    _ _ = refl
Lemma[R] Succ    _ _ = ap succ
Lemma[R](Rec{ρ}) x _ {α} {a} χ {φ} {f} ξ = R[KEᶥ] ρ x claim
 where
  claim : (i : )  R x (rec α  k  φ  _  k)) i) (rec a f i)  
  claim  0       = χ
  claim (succ i) = ξ refl (claim i)
Lemma[R] Pair _ _ = λ χ₀ χ₁  χ₀ , χ₁
Lemma[R] Pr1  _ _ = pr₁
Lemma[R] Pr2  _ _ = pr₂
Lemma[R] Inj1 _ _ = λ χ  χ
Lemma[R] Inj2 _ _ = λ χ  χ
Lemma[R](Case{ρ}) x _ χ η {ω} {w} = R[KE⁺] ρ x (case _ _) (case _ _) χ η {ω} {w}

\end{code}

■ Detailed proofs

\begin{code}

R⁺≡LL : {σ ρ : Ty} {x :  X ⟧ʸ}
       {ω :   σ  ρ ⟩ᴶ ⟧ʸ} {w :  σ  ρ ⟧ʸ}
       {α :   σ ⟩ᴶ ⟧ʸ} {a :  σ ⟧ʸ}
       ω x  inl α  w  inl a
       R x α a  R x ω w
R⁺≡LL e refl = sym (case⁼ˡ e)

R⁺≡RR : {σ ρ : Ty} {x :  X ⟧ʸ}
       {ω :   σ  ρ ⟩ᴶ ⟧ʸ} {w :  σ  ρ ⟧ʸ}
       {β :   ρ ⟩ᴶ ⟧ʸ} {b :  ρ ⟧ʸ}
       ω x  inr β  w  inr b
       R x β b  R x ω w
R⁺≡RR e refl = sym (case⁼ʳ e)

{- Proof of
R[KEᶥ] : (ρ : Ty) {Γ : Cxt} {γ : ⟦ Γ ⟧ˣ} (x : ⟦ X ⟧ʸ)
       → {f : ℕ → ⟦ ⟨ ρ ⟩ᴶ ⟧ʸ} {g : ℕ → ⟦ ρ ⟧ʸ}
       → ((i : ℕ) → R x (f i) (g i))
       → R x (⟦ KE ρ ⟧ᵐ γ f) g
-}
R[KEᶥ]  ι      x ζ χ = trans (ζ _) (ap _ χ)
R[KEᶥ] (τ  ρ) x ζ χ = λ ξ  R[KEᶥ] ρ x  i  ζ i ξ) χ
R[KEᶥ] (τ  ρ) x ζ χ = R[KEᶥ] τ x (pr₁  ζ) χ , R[KEᶥ] ρ x (pr₂  ζ) χ
R[KEᶥ] (τ  ρ) x {f} {g} ζ {φ} {n} χ = claim₀ (g n) (ζ n) claim₁
 where
  claim₀ : {δ :   τ  ρ ⟩ᴶ ⟧ʸ} (d :  τ  ρ ⟧ʸ)
          R x (f n) d  f n x  δ x  R x δ d
  claim₀ (inl a) ξ e = transport (case  α  R x α a)  _  𝟘)) e ξ
  claim₀ (inr b) ξ e = transport (case  _  𝟘)  β  R x β b)) e ξ
  claim₁ : f n x  f (φ x) x
  claim₁ = ap  k  f k x) χ

{- Proof of
R[KE⁺] : (ρ : Ty) (x : ⟦ X ⟧ʸ) {σ τ : Ty} {Γ : Cxt} {γ : ⟦ Γ ⟧ˣ}
       → (φ : ⟦ ⟨ σ ⟩ᴶ ⟧ʸ + ⟦ ⟨ τ ⟩ᴶ ⟧ʸ → ⟦ ⟨ ρ ⟩ᴶ ⟧ʸ) (f : ⟦ σ ⟧ʸ + ⟦ τ ⟧ʸ → ⟦ ρ ⟧ʸ)
       → ({α : ⟦ ⟨ σ ⟩ᴶ ⟧ʸ} {a : ⟦ σ ⟧ʸ} → R x α a → R x (φ (inl α)) (f (inl a)))
       → ({β : ⟦ ⟨ τ ⟩ᴶ ⟧ʸ} {b : ⟦ τ ⟧ʸ} → R x β b → R x (φ (inr β)) (f (inr b)))
       → R x (⟦ KE ρ ⟧ᵐ γ φ) f
-}
R[KE⁺] ι x φ f ζ ξ {ω} {inl a} χ with inspect (ω x)
... | inl α with≡ e = trans claim₀ claim₁
 where
  θ : R x α a
  θ = transport (case _ _) e χ
  claim₀ : f (inl a)  φ (inl α) x
  claim₀ = ζ θ
  claim₁ : φ (inl α) x  φ (ω x) x
  claim₁ = ap  z  φ z x) (sym e)
... | inr β with≡ e = 𝟘-elim (transport (case _ _) e χ)
R[KE⁺] ι x φ f ζ ξ {ω} {inr b} χ with inspect (ω x)
... | inl α with≡ e = 𝟘-elim (transport (case _ _) e χ)
... | inr β with≡ e = trans claim₀ claim₁
 where
  θ : R x β b
  θ = transport (case _ _) e χ
  claim₀ : f (inr b)  φ (inr β) x
  claim₀ = ξ θ
  claim₁ : φ (inr β) x  φ (ω x) x
  claim₁ = ap  z  φ z x) (sym e)
R[KE⁺] (ρ  ρ') x φ f ζ ξ χ = R[KE⁺] ρ x (pr₁  φ) (pr₁  f) (pr₁  ζ) (pr₁  ξ) χ ,
                              R[KE⁺] ρ' x (pr₂  φ) (pr₂  f) (pr₂  ζ) (pr₂  ξ) χ
R[KE⁺] (ρ  ρ') x φ f ζ ξ {ω} {inl a} χ with inspect (ω x)
... | inl α with≡ e = goal
 where
  θ : R x α a
  θ = transport (case _ _) e χ
  claim₀ : R x (φ (ω x)) (f (inl a))
  claim₀ = transport  z  R x (φ z) (f (inl a))) (sym e) (ζ θ)
  goal : R x  y  φ (ω y) y) (f (inl a))
  goal with inspect (f (inl a)) | inspect (φ (ω x) x)
  ... | inl u with≡ ef | inl v with≡  = transport  X  X) (R⁺≡LL  ef) claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inl u) -- case (λ γ → R x γ u) (λ _ → 𝟘) (φ (ω x) x)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : R x v u -- case (λ γ → R x γ u) (λ _ → 𝟘) (inl v)
    claim₂ = transport (case _ _)  claim₁
  ... | inl u with≡ ef | inr t with≡  = 𝟘-elim claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inl u)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : 𝟘
    claim₂ = transport (case _ _)  claim₁
  ... | inr s with≡ ef | inl v with≡  = 𝟘-elim claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inr s) -- case (λ _ → 𝟘) (λ γ → R x γ s) (φ (ω x) x)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : 𝟘
    claim₂ = transport (case _ _)  claim₁
  ... | inr s with≡ ef | inr t with≡  = transport  X  X) (R⁺≡RR  ef) claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inr s) -- case (λ _ → 𝟘) (λ γ → R x γ s) (φ (ω x) x)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : R x t s
    claim₂ = transport (case _ _)  claim₁
R[KE⁺] (ρ  ρ') x φ f ζ ξ {ω} {inl a} χ | inr β with≡ e = 𝟘-elim (transport (case _ _) e χ)
R[KE⁺] (ρ  ρ') x φ f ζ ξ {ω} {inr b} χ with inspect (ω x)
... | inl α with≡ e = 𝟘-elim (transport (case _ _) e χ)
... | inr β with≡ e = goal
 where
  θ : R x β b
  θ = transport (case _ _) e χ
  claim₀ : R x (φ (ω x)) (f (inr b))
  claim₀ = transport  z  R x (φ z) (f (inr b))) (sym e) (ξ θ)
  goal : R x  y  φ (ω y) y) (f (inr b))
  goal with inspect (f (inr b)) | inspect (φ (ω x) x)
  ... | inl u with≡ ef | inl v with≡  = transport  X  X) (R⁺≡LL  ef) claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inl u) -- case (λ γ → R x γ u) (λ _ → 𝟘) (φ (ω x) x)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : R x v u -- case (λ γ → R x γ u) (λ _ → 𝟘) (inl v)
    claim₂ = transport (case _ _)  claim₁
  ... | inl u with≡ ef | inr t with≡  = 𝟘-elim claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inl u)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : 𝟘
    claim₂ = transport (case _ _)  claim₁
  ... | inr s with≡ ef | inl v with≡  = 𝟘-elim claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inr s) -- case (λ _ → 𝟘) (λ γ → R x γ s) (φ (ω x) x)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : 𝟘
    claim₂ = transport (case _ _)  claim₁
  ... | inr s with≡ ef | inr t with≡  = transport  X  X) (R⁺≡RR  ef) claim₂
   where
    claim₁ : R {ρ  ρ'} x (φ (ω x)) (inr s) -- case (λ _ → 𝟘) (λ γ → R x γ s) (φ (ω x) x)
    claim₁ = transport (R x _) ef claim₀
    claim₂ : R x t s
    claim₂ = transport (case _ _)  claim₁
R[KE⁺] (ρ  ρ') x φ f ζ ξ χ η = R[KE⁺] ρ' x  z  φ z _)  z  f z _)  θ  ζ θ η)  θ  ξ θ η) χ

\end{code}