module DStermK where

open import Data.Nat
open import Data.Product
open import Relation.Binary.PropositionalEquality

-- type
data typK : Set where
  Nat          : typK
  _⇒_cps[_,_]  : typK  typK  typK  typK  typK

data conttypK : Set where
  K_▷_ : typK  typK  conttypK
  •_ : typK  conttypK

Δ-typeK : conttypK  typK  typK  Set
Δ-typeK (K τ₁′  τ₂′) τ₁ τ₂ = τ₁′  τ₁ × τ₂′  τ₂
Δ-typeK ( τ) τ₁ τ₂ = τ  τ₁ × τ  τ₂

-- source kernel term
mutual
  data valueK[_]_ (var : typK  Set) : typK  Set where
    -- x
    Var   : {τ₁ : typK}  var τ₁  valueK[ var ] τ₁
    -- n
    Num   :   valueK[ var ] Nat
    -- λx.M
    Fun   : {τ₀ τ₁ τ₃ τ₄ : typK} 
            (var τ₀  termK[ var , K τ₁  τ₃ ] τ₄) 
            valueK[ var ] (τ₀  τ₁ cps[ τ₃ , τ₄ ])
    -- S
    Shift : {τ₁ τ₂ τ₃ τ₄ τ₅ : typK} 
            valueK[ var ]
            (((τ₁  τ₂ cps[ τ₃ , τ₃ ])  τ₄ cps[ τ₄ , τ₅ ])
              τ₁ cps[ τ₂ , τ₅ ])

  data termK[_,_]_ (var : typK  Set) : conttypK  typK  Set where
    -- K V
    Ret  : {τ₁ τ₂ : typK}  {Δ : conttypK} 
           pcontextK[ var , Δ , τ₁ ] τ₂ 
           valueK[ var ] τ₁ 
           termK[ var , Δ ] τ₂
    -- K (V W)
    App  : {τ₁ τ₂ τ₃ τ₄ : typK}  {Δ : conttypK} 
           valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ]) 
           valueK[ var ] τ₂ 
           pcontextK[ var , Δ , τ₁ ] τ₃ 
           termK[ var , Δ ] τ₄
    -- K (Sk.M)
    Shift2 : {τ₁ τ₂ τ₃ τ₄ τ₅ : typK}  {Δ : conttypK} 
           (var (τ₁  τ₂ cps[ τ₃ , τ₃ ])  termK[ var , K τ₄  τ₄ ] τ₅) 
           pcontextK[ var , Δ , τ₁ ] τ₂ 
           termK[ var , Δ ] τ₅
    -- K <M>
    RetE : {τ τ₁ τ₂ : typK}  {Δ : conttypK} 
           pcontextK[ var , Δ , τ₁ ] τ₂ 
           termK[ var ,  τ ] τ₁ 
           termK[ var , Δ ] τ₂

  data pcontextK[_,_,_]_ (var : typK  Set) : conttypK  typK  typK  Set where
    -- k []
    KVar  : {τ₁ τ₂ : typK} 
            pcontextK[ var , K τ₁  τ₂ , τ₁ ] τ₂
    -- []
    KId   : {τ₁ : typK} 
            pcontextK[ var ,  τ₁ , τ₁ ] τ₁
    -- let x = [] in M
    KLet  : {τ₁ τ₂ : typK}  {Δ : conttypK} 
            (e₂ : var τ₁  termK[ var , Δ ] τ₂) 
            pcontextK[ var , Δ , τ₁ ] τ₂

-- example
-- λx.λk.k@x
val1 : {var : typK  Set}  {τ₁ τ₂ : typK} 
       valueK[ var ] (τ₁  τ₁ cps[ τ₂ , τ₂ ])
val1 = Fun  x  Ret KVar (Var x))

-- interpreter
〚_〛 : typK  Set
 Nat  = 
 τ₂  τ₁ cps[ τ₃ , τ₄ ]  =
    τ₂   ( τ₁    τ₃ )   τ₄ 

〚_〛' : conttypK  Set
 K τ₂  τ₁ 〛' =  τ₂    τ₁ 
  τ 〛' =  τ    τ 

mutual
  gv : {τ : typK}  valueK[ 〚_〛 ] τ   τ 
  gv (Var x) = x
  gv (Num n) = n
  gv (Fun e) = λ x k  g (e x) k
  gv Shift = λ v k  v  x₂ k₂  k₂ (k x₂))  x  x)

  g : {τ : typK}  {Δ : conttypK}  termK[ 〚_〛 , Δ ] τ   Δ 〛'   τ 
  g (Ret k v) Δ = (gc k Δ) (gv v)
  g (App v w k) Δ = (gv v) (gv w) (gc k Δ)
  g (Shift2 e k) Δ = g (e  x₂ k₂  k₂ (gc k Δ x₂)))  x  x)
  g (RetE k e) Δ = (gc k Δ) (g e  x  x))

  gc : {τ₁ τ₂ : typK} {Δ : conttypK} 
       pcontextK[ 〚_〛 , Δ , τ₁ ] τ₂   Δ 〛'    τ₁    τ₂ 
  gc KVar k = k
  gc KId Δ = λ x  x
  gc (KLet e) Δ = λ x  g (e x) Δ

mutual
  data SubstVK {var : typK  Set} : {τ τ₁ : typK} 
               (var τ  valueK[ var ] τ₁) 
               valueK[ var ] τ 
               valueK[ var ] τ₁  Set where
    sVar=  : {τ : typK} {v : valueK[ var ] τ} 
             SubstVK  x  Var x) v v
    sVar≠  : {τ τ₁ : typK} {v : valueK[ var ] τ} {x : var τ₁} 
             SubstVK  _  Var x) v (Var x)
    sNum   : {τ : typK} {v : valueK[ var ] τ} {n : } 
             SubstVK  _  Num n) v (Num n)
    sFun   : {τ′ τ₀ τ₁ τ₃ τ₄ : typK} 
             {e  : var τ′  var τ₀  termK[ var , K τ₁  τ₃ ] τ₄} 
             {v  : valueK[ var ] τ′} 
             {e′ : var τ₀  termK[ var , K τ₁  τ₃ ] τ₄} 
             ((x : var τ₀)  SubstK  y  (e y) x) v (e′ x)) 
             SubstVK  y  Fun  x  (e y) x)) v (Fun e′)
    sShift : {τ₁ τ₂ τ₃ τ₄ τ₅ τ : typK} {v : valueK[ var ] τ} 
             SubstVK  _  Shift {τ₁ = τ₁} {τ₂} {τ₃} {τ₄} {τ₅})
                     v Shift

  data SubstK {var : typK  Set} : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              (var τ₁  termK[ var , Δ ] τ₂) 
              valueK[ var ] τ₁ 
              termK[ var , Δ ] τ₂  Set where
    sRet   : {τ τ₁ τ₂ : typK}  {Δ : conttypK} 
             {k₁ : var τ  pcontextK[ var , Δ , τ₁ ] τ₂} 
             {v₁ : var τ  valueK[ var ] τ₁} 
             {v : valueK[ var ] τ} 
             {k₂ : pcontextK[ var , Δ , τ₁ ] τ₂} 
             {v₂ : valueK[ var ] τ₁} 
             SubstCK k₁ v k₂ 
             SubstVK v₁ v v₂ 
             SubstK  y  Ret (k₁ y) (v₁ y)) v (Ret k₂ v₂)
    sApp   : {τ τ₁ τ₂ τ₃ τ₄ : typK}  {Δ : conttypK} 
             {v₁ : var τ  valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])} 
             {w₁ : var τ  valueK[ var ] τ₂} 
             {k₁ : var τ  pcontextK[ var , Δ , τ₁ ] τ₃} 
             {v  : valueK[ var ] τ} 
             {v₂ : valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])} 
             {w₂ : valueK[ var ] τ₂} 
             {k₂ : pcontextK[ var , Δ , τ₁ ] τ₃} 
             SubstVK v₁ v v₂ 
             SubstVK w₁ v w₂ 
             SubstCK k₁ v k₂ 
             SubstK  y  (App (v₁ y) (w₁ y) (k₁ y))) v (App v₂ w₂ k₂)
    sShift2 : {τ τ₁ τ₂ τ₃ τ₄ τ₅ : typK}  {Δ : conttypK} 
             {e₁ : var τ  var (τ₁  τ₂ cps[ τ₃ , τ₃ ]) 
                   termK[ var , K τ₄  τ₄ ] τ₅} 
             {k₁ : var τ  pcontextK[ var , Δ , τ₁ ] τ₂} 
             {v  : valueK[ var ] τ} 
             {e₂ : var (τ₁  τ₂ cps[ τ₃ , τ₃ ]) 
                   termK[ var , K τ₄  τ₄ ] τ₅} 
             {k₂ : pcontextK[ var , Δ , τ₁ ] τ₂} 
             ((x : var (τ₁  τ₂ cps[ τ₃ , τ₃ ])) 
              SubstK  y  (e₁ y) x) v (e₂ x)) 
             SubstCK k₁ v k₂ 
             SubstK  y  (Shift2 (e₁ y) (k₁ y))) v (Shift2 e₂ k₂)
    sRetE  : {τ τ₁ τ₂ α : typK}  {Δ : conttypK} 
             {k₁ : var τ  pcontextK[ var , Δ , τ₁ ] τ₂} 
             {e₁ : var τ  termK[ var ,  α ] τ₁} 
             {v  : valueK[ var ] τ} 
             {k₂ : pcontextK[ var , Δ , τ₁ ] τ₂} 
             {e₂ : termK[ var ,  α ] τ₁} 
             SubstCK k₁ v k₂  SubstK e₁ v e₂ 
             SubstK  y  (RetE (k₁ y) (e₁ y))) v (RetE k₂ e₂)

  data SubstCK {var : typK  Set} : {τ α β : typK}  {Δ : conttypK} 
               (var τ  pcontextK[ var , Δ , α ] β) 
               valueK[ var ] τ 
               pcontextK[ var , Δ , α ] β  Set where
    sKVar≠   : {τ τ₁ τ₂ : typK} 
               {v : valueK[ var ] τ} 
               SubstCK  _  KVar {τ₁ = τ₁} {τ₂}) v KVar
    sKId     : {τ τ₁ : typK} 
               {v : valueK[ var ] τ} 
               SubstCK  _  KId {τ₁ = τ₁}) v KId
    sKLet    : {τ τ₁ τ₂ : typK}  {Δ : conttypK} 
               {e₁ : var τ  var τ₁  termK[ var , Δ ] τ₂} 
               {v  : valueK[ var ] τ} 
               {e₂ : var τ₁  termK[ var , Δ ] τ₂} 
               ((x : var τ₁)  SubstK  y  (e₁ y) x) v (e₂ x)) 
               SubstCK  y  KLet (e₁ y)) v (KLet e₂)

mutual
  data SubstK₂ {var : typK  Set} :
               {τ₁ α β : typK}  {Δ : conttypK} 
               termK[ var , K α  β ] τ₁  -- has to be K
               pcontextK[ var , Δ , α ] β 
               termK[ var , Δ ] τ₁  Set where
    sRet    : {τ₁ τ₂ α β : typK}  {Δ : conttypK}
              {k₁ : pcontextK[ var , K α  β , τ₁ ] τ₂} 
              {v  : valueK[ var ] τ₁} 
              {c  : pcontextK[ var , Δ , α ] β} 
              {k₂ : pcontextK[ var , Δ , τ₁ ] τ₂} 
              SubstCK₂ k₁ c k₂ 
              SubstK₂ (Ret k₁ v) c (Ret k₂ v)
    sApp    : {τ₁ τ₂ τ₃ τ₄ α β : typK}  {Δ : conttypK} 
              {v  : valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])} 
              {w  : valueK[ var ] τ₂} 
              {k₁ : pcontextK[ var , K α  β , τ₁ ] τ₃} 
              {c  : pcontextK[ var , Δ , α ] β} 
              {k₂ : pcontextK[ var , Δ , τ₁ ] τ₃} 
              SubstCK₂ k₁ c k₂ 
              SubstK₂ (App v w k₁) c (App v w k₂)
    sShift2 : {τ₁ τ₂ τ₃ τ₄ τ₅ α β : typK}  {Δ : conttypK} 
              {e  : var (τ₁  τ₂ cps[ τ₃ , τ₃ ]) 
                    termK[ var , K τ₄  τ₄ ] τ₅} 
              {k₁ : pcontextK[ var , K α  β , τ₁ ] τ₂} 
              {c  : pcontextK[ var , Δ , α ] β} 
              {k₂ : pcontextK[ var , Δ , τ₁ ] τ₂} 
              SubstCK₂ k₁ c k₂ 
              SubstK₂ (Shift2 e k₁) c (Shift2 e k₂)
    sRetE   : {τ₁ τ₂ α β γ : typK}  {Δ : conttypK} 
              {k₁ : pcontextK[ var , K α  β , τ₁ ] τ₂} 
              {e  : termK[ var ,  γ ] τ₁} 
              {c  : pcontextK[ var , Δ , α ] β} 
              {k₂ : pcontextK[ var , Δ , τ₁ ] τ₂} 
              SubstCK₂ k₁ c k₂ 
              SubstK₂ (RetE k₁ e) c (RetE k₂ e)

  data SubstCK₂ {var : typK  Set} :
                {τ₁ τ₂ α β : typK}  {Δ : conttypK} 
                pcontextK[ var , K α  β , τ₁ ] τ₂ 
                pcontextK[ var , Δ , α ] β 
                pcontextK[ var , Δ , τ₁ ] τ₂  Set where
    sKVar=  : {α β : typK}  {Δ : conttypK} 
              {c : pcontextK[ var , Δ , α ] β} 
              SubstCK₂ KVar c c
    sKLet   : {τ₁ τ₂ α β : typK}  {Δ : conttypK} 
              {e₁ : var τ₁  termK[ var , K α  β ] τ₂} 
              {c  : pcontextK[ var , Δ , α ] β} 
              {e₂ : var τ₁  termK[ var , Δ ] τ₂} 
              ((x : var τ₁)  SubstK₂ (e₁ x) c (e₂ x)) 
              SubstCK₂ (KLet e₁) c (KLet e₂)

-- reduction rules
mutual
  data ReduceK {var : typK  Set} : {τ₁ : typK}  {Δ : conttypK} 
               termK[ var , Δ ] τ₁ 
               termK[ var , Δ ] τ₁  Set where
    -- K ((λx.M) V) -> M[x:=V][k:=K]
    RBetaV  : {τ₁ τ₂ τ₃ τ₄ : typK}  {Δ : conttypK} 
              {e₁ : var τ₂  termK[ var , K τ₁  τ₃ ] τ₄} 
              {v : valueK[ var ] τ₂} 
              {c : pcontextK[ var , Δ , τ₁ ] τ₃} 
              {e₁′ : termK[ var , K τ₁  τ₃ ] τ₄} 
              {e₂ : termK[ var , Δ ] τ₄} 
              SubstK e₁ v e₁′ 
              SubstK₂ e₁′ c e₂ 
              ReduceK (App (Fun  x  e₁ x)) v c) e₂
    -- let x = V in M -> M[x:=V]
    RBetaLet : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {e  : var τ₁  termK[ var , Δ ] τ₂} 
              {v  : valueK[ var ] τ₁} 
              {e′ : termK[ var , Δ ] τ₂} 
              SubstK e v e′ 
              ReduceK (Ret (KLet e) v) e′
    -- K <J[S@V]> -> K <V@(λy.<J[y]>)>
    RShift  : {τ₁ τ₂ τ₃ τ₄ τ₅ τ₆ : typK}  {Δ : conttypK} 
              {v  : valueK[ var ]
                    ((τ₁  τ₂ cps[ τ₃ , τ₃ ])  τ₄ cps[ τ₄ , τ₅ ])} 
              {j  : pcontextK[ var ,  τ₄ , τ₁ ] τ₂} 
              {k : pcontextK[ var , Δ , τ₅ ] τ₆} 
              ReduceK (RetE k (App Shift v j))
                      (RetE k (App v (Fun  y  RetE KVar (Ret j (Var y))))
                                   KId))
    -- K <J[Sk.M]> -> K <(λk.M)@(λy.<J[y]>)>
    RShift2 : {τ₁ τ₂ τ₃ τ₄ τ₅ τ₆ : typK}  {Δ : conttypK} 
              {e  : var (τ₁  τ₂ cps[ τ₃ , τ₃ ]) 
                    termK[ var ,  K τ₄  τ₄ ] τ₅} 
              {j  : pcontextK[ var ,  τ₄ , τ₁ ] τ₂} 
              {k : pcontextK[ var , Δ , τ₅ ] τ₆} 
              ReduceK (RetE k (Shift2 e j))
                      (RetE k (App (Fun e)
                                   (Fun  y  RetE KVar (Ret j (Var y))))
                                   KId))
    -- k <V> -> k V
    RReset  : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {v : valueK[ var ] τ₁} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₂} 
              ReduceK (RetE k (Ret KId v)) (Ret k v)

    -- congruence rules
    RRet₁   : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {k k' : pcontextK[ var , Δ , τ₁ ] τ₂} 
              {v : valueK[ var ] τ₁} 
              ReduceCK k k' 
              ReduceK (Ret k v) (Ret k' v)
    RRet₂   : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₂} 
              {v v' : valueK[ var ] τ₁} 
              ReduceVK v v' 
              ReduceK (Ret k v) (Ret k v')
    RApp₁   : {τ₁ τ₂ τ₃ τ₄ : typK}  {Δ : conttypK} 
              {v v' : valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])} 
              {w : valueK[ var ] τ₂} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₃} 
              ReduceVK v v' 
              ReduceK (App v w k) (App v' w k)
    RApp₂   : {τ₁ τ₂ τ₃ τ₄ : typK}  {Δ : conttypK} 
              {v : valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])} 
              {w w' : valueK[ var ] τ₂} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₃} 
              ReduceVK w w' 
              ReduceK (App v w k) (App v w' k)
    RApp₃   : {τ₁ τ₂ τ₃ τ₄ : typK}  {Δ : conttypK} 
              {v : valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])} 
              {w : valueK[ var ] τ₂} 
              {k k' : pcontextK[ var , Δ , τ₁ ] τ₃} 
              ReduceCK k k' 
              ReduceK (App v w k) (App v w k')
    RShift₁  : {τ₁ τ₂ τ₃ τ₄ τ₅ : typK}  {Δ : conttypK} 
              {k k' : pcontextK[ var , Δ , τ₁ ] τ₂} 
              {e : (var (τ₁  τ₂ cps[ τ₃ , τ₃ ]) 
                   termK[ var , K τ₄  τ₄ ] τ₅)} 
              ReduceCK k k' 
              ReduceK (Shift2 e k) (Shift2 e k')
    RShift₂  : {τ₁ τ₂ τ₃ τ₄ τ₅ : typK}  {Δ : conttypK} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₂} 
              {e e' : (var (τ₁  τ₂ cps[ τ₃ , τ₃ ]) 
                   termK[ var , K τ₄  τ₄ ] τ₅)} 
              ((x : var (τ₁  τ₂ cps[ τ₃ , τ₃ ]))  ReduceK (e x) (e' x)) 
              ReduceK (Shift2 e k) (Shift2 e' k)
    RRetE₁  : {τ τ₁ τ₂ : typK}  {Δ : conttypK} 
              {k k' : pcontextK[ var , Δ , τ₁ ] τ₂} 
              {e : termK[ var ,  τ ] τ₁} 
              ReduceCK k k' 
              ReduceK (RetE k e) (RetE k' e)
    RRetE₂  : {τ τ₁ τ₂ : typK}  {Δ : conttypK} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₂} 
              {e e' : termK[ var ,  τ ] τ₁} 
              ReduceK e e' 
              ReduceK (RetE k e) (RetE k e')
    -- closure rules
    RId     : {τ₁ : typK} {Δ : conttypK} 
              {e : termK[ var , Δ ] τ₁} 
              ReduceK e e
    RTrans  : {τ₁ : typK} {Δ : conttypK} 
              {e₁ e₂ e₃ : termK[ var , Δ ] τ₁} 
              ReduceK e₁ e₂ 
              ReduceK e₂ e₃ 
              ReduceK e₁ e₃

  data ReduceVK {var : typK  Set} : {τ₁ : typK} 
                valueK[ var ] τ₁ 
                valueK[ var ] τ₁  Set where
    -- λx.V x -> V
    REtaV   : {τ₁ τ₂ τ₃ τ₄ : typK} 
              (v : valueK[ var ] (τ₂  τ₁ cps[ τ₃ , τ₄ ])) 
              ReduceVK (Fun  x  App v (Var x) KVar)) v

    -- congruence rule
    RFun    : {τ₀ τ₁ τ₃ τ₄ : typK} 
              (e e' : var τ₀  termK[ var , K τ₁  τ₃ ] τ₄) 
              ((x : var τ₀)  ReduceK (e x) (e' x)) 
              ReduceVK (Fun e) (Fun e')
    -- closure rules
    RId     : {τ₁ : typK} 
              {v : valueK[ var ] τ₁} 
              ReduceVK v v
    RTrans  : {τ₁ : typK} 
              {v₁ v₂ v₃ : valueK[ var ] τ₁} 
              ReduceVK v₁ v₂ 
              ReduceVK v₂ v₃ 
              ReduceVK v₁ v₃

  data ReduceCK {var : typK  Set} : {τ₁ τ₂ : typK}  {Δ : conttypK} 
                pcontextK[ var , Δ , τ₁ ] τ₂ 
                pcontextK[ var , Δ , τ₁ ] τ₂  Set where
    -- let x = [] in K x -> K
    REtaLet : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              (k : pcontextK[ var , Δ , τ₁ ] τ₂) 
              ReduceCK (KLet  x  Ret k (Var x))) k

    -- congruence rule
    RKLet   : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {e e' : var τ₁  termK[ var , Δ ] τ₂} 
              ((x : var τ₁)  ReduceK (e x) (e' x)) 
              ReduceCK (KLet e) (KLet e')
    -- closure rules
    RId     : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {k : pcontextK[ var , Δ , τ₁ ] τ₂} 
              ReduceCK k k
    RTrans  : {τ₁ τ₂ : typK}  {Δ : conttypK} 
              {k₁ k₂ k₃ : pcontextK[ var , Δ , τ₁ ] τ₂} 
              ReduceCK k₁ k₂ 
              ReduceCK k₂ k₃ 
              ReduceCK k₁ k₃

-- equational reasoning
module Reasoning where

  open import Relation.Binary.PropositionalEquality

  infix  3 _∎
  infixr 2 _⟶⟨_⟩_ _≡⟨_⟩_
  infix  1 begin_

  begin_ : {var : typK  Set} {τ₁ : typK} {Δ : conttypK} 
           {e₁ e₂ : termK[ var , Δ ] τ₁} 
           ReduceK e₁ e₂  ReduceK e₁ e₂
  begin_ red = red

  _⟶⟨_⟩_ : {var : typK  Set} {τ₁ : typK} {Δ : conttypK} 
            (e₁ {e₂ e₃} : termK[ var , Δ ] τ₁) 
            ReduceK e₁ e₂  ReduceK e₂ e₃  ReduceK e₁ e₃
  _⟶⟨_⟩_ e₁ {e₂} {e₃} e₁-red-e₂ e₂-red-e₃ = RTrans e₁-red-e₂ e₂-red-e₃

  _≡⟨_⟩_ : {var : typK  Set} {τ₁ : typK} {Δ : conttypK} 
           (e₁ {e₂ e₃} : termK[ var , Δ ] τ₁) 
           e₁  e₂  ReduceK e₂ e₃ 
           ReduceK e₁ e₃
  _≡⟨_⟩_ e₁ {e₂} {e₃} refl e₂-red-e₃ = e₂-red-e₃

  _∎ : {var : typK  Set} {τ₁ : typK} {Δ : conttypK} 
       (e : termK[ var , Δ ] τ₁)  ReduceK e e
  _∎ e = RId

-- lemma
mutual
  SubstKV≠ : {var : typK  Set} {τ₁ τ : typK} 
             (v₁ : valueK[ var ] τ₁) 
             {v : valueK[ var ] τ} 
             SubstVK  _  v₁) v v₁
  SubstKV≠ (Var x) = sVar≠
  SubstKV≠ (Num n) = sNum
  SubstKV≠ (Fun e) = sFun  x  SubstK≠ (e x))
  SubstKV≠ Shift = sShift

  SubstK≠ : {var : typK  Set} {τ₄ τ : typK} {Δ : conttypK} 
            (e₁ : termK[ var , Δ ] τ₄) 
            {v : valueK[ var ] τ} 
            SubstK  _  e₁) v e₁
  SubstK≠ (Ret k v) = sRet (SubstKC≠ k) (SubstKV≠ v)
  SubstK≠ (App v w k) = sApp (SubstKV≠ v) (SubstKV≠ w) (SubstKC≠ k)
  SubstK≠ (Shift2 e k) = sShift2  x  SubstK≠ (e x)) (SubstKC≠ k)
  SubstK≠ (RetE k e) = sRetE (SubstKC≠ k) (SubstK≠ e)

  SubstKC≠ : {var : typK  Set} {τ₂ τ₄ τ : typK} {Δ : conttypK} 
             (k₁ : pcontextK[ var , Δ , τ₂ ] τ₄) 
             {v : valueK[ var ] τ} 
             SubstCK  _  k₁) v k₁
  SubstKC≠ KVar = sKVar≠
  SubstKC≠ KId = sKId
  SubstKC≠ (KLet e) = sKLet  x  SubstK≠ (e x))

lemma-SubstK₂-KVar : {var : typK  Set} {τ₁ τ₂ τ₃ : typK}
                     (e : termK[ var , K τ₂  τ₃ ] τ₁) 
                     SubstK₂ e KVar e
lemma-SubstK₂-KVar (Ret KVar v) = sRet sKVar=
lemma-SubstK₂-KVar (Ret (KLet e₂) v) =
  sRet (sKLet  x  lemma-SubstK₂-KVar (e₂ x)))
lemma-SubstK₂-KVar (App v w KVar) = sApp sKVar=
lemma-SubstK₂-KVar (App v w (KLet e₂)) =
  sApp (sKLet  x  lemma-SubstK₂-KVar (e₂ x)))
lemma-SubstK₂-KVar (Shift2 e KVar) = sShift2 sKVar=
lemma-SubstK₂-KVar (Shift2 e (KLet e₂)) =
  sShift2 (sKLet  x  lemma-SubstK₂-KVar (e₂ x)))
lemma-SubstK₂-KVar (RetE KVar e) = sRetE sKVar=
lemma-SubstK₂-KVar (RetE (KLet e₂) e) =
  sRetE (sKLet  x  lemma-SubstK₂-KVar (e₂ x)))