{-# OPTIONS --copatterns --sized-types #-}

module Substitution where

open import Library
open import SizedInfiniteTypes
open import Terms

-- VarTm n specifies whether the substitution produces variables or terms.
-- The index is used to impose an order on the constructors
-- and so pass termination checking in lift/subst.
data VarTm :   Set where
  `Var : VarTm 0
  `Tm  : VarTm 1

max01 :     
max01 0 m = m
max01 n m = n

_∙VT_ :  {m n}  VarTm m  VarTm n  VarTm (max01 m n)
`Var ∙VT vt = vt
`Tm  ∙VT vt = `Tm

VT :  {m}  VarTm m  Cxt  Ty  Set
VT `Var Γ a = Var Γ a
VT `Tm  Γ a = Tm Γ a


vt2tm :  {Γ a}   {m} vt  VT {m} vt Γ a  Tm Γ a
vt2tm `Var  x = var x
vt2tm `Tm t = t

RenSub :  {m}  VarTm m  Cxt  Cxt  Set
RenSub vt Γ Δ =  {a}  Var Γ a  VT vt Δ a

mutual
  -- Lifiting a substitution

  lifts :  {m vt Γ Δ a}  RenSub {m} vt Γ Δ  RenSub vt (a  Γ) (a  Δ)
  lifts {vt = `Var} σ (zero)    = zero
  lifts {vt = `Var} σ (suc x) = suc (σ x)
  lifts {vt = `Tm}  σ (zero)    = var (zero)
  lifts {vt = `Tm}  σ (suc x) = subst {vt = `Var} suc (σ x)

  -- Performing a substitution

  subst :  {m vt Γ Δ τ}  RenSub {m} vt Γ Δ  Tm Γ τ  Tm Δ τ

  subst σ (abs t)     = abs (subst (lifts σ) t)
  subst σ (app t u)   = app (subst σ t) (subst σ u)
  subst σ ( t)       =  (subst σ t)
  subst σ (t  u)     = (subst σ t)  (subst σ u)
  subst σ (pair t u)  = pair (subst σ t) (subst σ u)
  subst σ (fst t)     = fst (subst σ t)
  subst σ (snd t)     = snd (subst σ t)
--  subst σ (cast eq t) = cast eq (subst σ t)
  subst σ (var x)     = vt2tm _ (σ x)


data IndSubst {m vt Γ Δ} (σ : RenSub {m} vt Γ Δ) :  {τ}  Tm Γ τ  Tm Δ τ  Set where
  var  : ∀{a t}          (x : Var Γ a)  vt2tm _ (σ x)  t          IndSubst σ (var x) t
  abs  : ∀{a b}{t : Tm (a  Γ) b}{t'}  IndSubst (lifts σ) t t'  IndSubst σ (abs t) (abs t')
  app  : ∀{a b}{t : Tm Γ (a →̂ b)}{u : Tm Γ a}{t' u'}  IndSubst σ t t'  IndSubst σ u u'  IndSubst σ (app t u) (app t' u')
  pair : ∀{a b}{t : Tm Γ a} {u : Tm Γ b}{t' u'}  IndSubst σ t t'  IndSubst σ u u'  IndSubst σ (pair t u) (pair t' u')
  fst  : ∀{a b}{t : Tm Γ (a ×̂ b)}{t'}  IndSubst σ t t'  IndSubst σ (fst t) (fst t')
  snd  : ∀{a b}{t : Tm Γ (a ×̂ b)}{t'}  IndSubst σ t t'  IndSubst σ (snd t) (snd t')
  ▹_   : ∀{a∞}{t : Tm Γ (force a∞)}{t'}  IndSubst σ t t'  IndSubst σ (▹_ {a∞ = a∞} t) ( t')

  -- `applicative'
  _∗_  : ∀{a : Ty}{b∞}{t : Tm Γ (▸̂ (delay a  b∞))} {u : Tm Γ ( a)}{t' u'}
           IndSubst σ t t'  IndSubst σ u u'  IndSubst σ (t  u) (t'  u')

--  cast : ∀{a b} (eq : a ≅ b) {t : Tm Γ a}{t'} → IndSubst σ t t'      → IndSubst σ (cast eq t) (cast eq t')

data IndRen {Γ Δ} (σ : RenSub `Var Γ Δ) :  {τ}  Tm Γ τ  Tm Δ τ  Set where
  var  : ∀{a y}          (x : Var Γ a)  (σ x)  y          IndRen σ (var x) (var y)
  abs  : ∀{a b}{t : Tm (a  Γ) b}{t'}  IndRen (lifts σ) t t'  IndRen σ (abs t) (abs t')
  app  : ∀{a b}{t : Tm Γ (a →̂ b)}{u : Tm Γ a}{t' u'}  IndRen σ t t'  IndRen σ u u'  IndRen σ (app t u) (app t' u')
  pair : ∀{a b}{t : Tm Γ a} {u : Tm Γ b}{t' u'}  IndRen σ t t'  IndRen σ u u'  IndRen σ (pair t u) (pair t' u')
  fst  : ∀{a b}{t : Tm Γ (a ×̂ b)}{t'}  IndRen σ t t'  IndRen σ (fst t) (fst t')
  snd  : ∀{a b}{t : Tm Γ (a ×̂ b)}{t'}  IndRen σ t t'  IndRen σ (snd t) (snd t')
  ▹_   : ∀{a∞}{t : Tm Γ (force a∞)}{t'}  IndRen σ t t'  IndRen σ (▹_ {a∞ = a∞} t) ( t')

  -- `applicative'
  _∗_  : ∀{a : Ty}{b∞}{t : Tm Γ (▸̂ (delay a  b∞))} {u : Tm Γ ( a)}{t' u'}
           IndRen σ t t'  IndRen σ u u'  IndRen σ (t  u) (t'  u')

--  cast : ∀{a b} (eq : a ≅ b) {t : Tm Γ a}{t'} → IndRen σ t t'      → IndRen σ (cast eq t) (cast eq t')

IndS→prop :  {m vt Γ Δ} (σ : RenSub {m} vt Γ Δ) {τ} {t : Tm Γ τ} {t' : Tm Δ τ}  IndSubst σ t t'  subst σ t  t'
IndS→prop σ (var x ≡.refl) = ≡.refl
IndS→prop σ (abs t)     = ≡.cong abs (IndS→prop (lifts σ) t)
IndS→prop σ (app t t₁)  = ≡.cong₂ app (IndS→prop σ t) (IndS→prop σ t₁)
IndS→prop σ (pair t t₁) = ≡.cong₂ pair (IndS→prop σ t) (IndS→prop σ t₁)
IndS→prop σ (fst t)     = ≡.cong fst (IndS→prop σ t)
IndS→prop σ (snd t)     = ≡.cong snd (IndS→prop σ t)
IndS→prop σ ( t)       = ≡.cong ▹_ (IndS→prop σ t)
IndS→prop σ (t  t₁)    = ≡.cong₂ _∗_ (IndS→prop σ t) (IndS→prop σ t₁)
--IndS→prop σ (cast eq t) = ≡.cong (cast eq) (IndS→prop σ t)

prop→IndS' :  {m vt Γ Δ} (σ : RenSub {m} vt Γ Δ) {τ} (t : Tm Γ τ)  IndSubst σ t (subst σ t)
prop→IndS' σ (var x) = var x ≡.refl
prop→IndS' σ (abs t)     = abs (prop→IndS' (lifts σ) t)
prop→IndS' σ (app t u)   = app (prop→IndS' σ t) (prop→IndS' σ u)
prop→IndS' σ ( t)       =  (prop→IndS' σ t)
prop→IndS' σ (t  u)     = (prop→IndS' σ t)  (prop→IndS' σ u)
prop→IndS' σ (pair t u)  = pair (prop→IndS' σ t) (prop→IndS' σ u)
prop→IndS' σ (fst t)     = fst (prop→IndS' σ t)
prop→IndS' σ (snd t)     = snd (prop→IndS' σ t)
--prop→IndS' σ (cast eq t) = cast eq (prop→IndS' σ t)

prop→IndS :  {m vt Γ Δ} (σ : RenSub {m} vt Γ Δ) {τ} {t : Tm Γ τ} {t' : Tm Δ τ}  subst σ t  t'  IndSubst σ t t'
prop→IndS _ ≡.refl = prop→IndS' _ _


Ind→prop :  {Γ Δ} (σ : RenSub `Var Γ Δ) {τ} {t : Tm Γ τ} {t' : Tm Δ τ}  IndRen σ t t'  subst σ t  t'
Ind→prop σ (var x ≡.refl) = ≡.refl
Ind→prop σ (abs t)     = ≡.cong abs (Ind→prop (lifts σ) t)
Ind→prop σ (app t t₁)  = ≡.cong₂ app (Ind→prop σ t) (Ind→prop σ t₁)
Ind→prop σ (pair t t₁) = ≡.cong₂ pair (Ind→prop σ t) (Ind→prop σ t₁)
Ind→prop σ (fst t)     = ≡.cong fst (Ind→prop σ t)
Ind→prop σ (snd t)     = ≡.cong snd (Ind→prop σ t)
Ind→prop σ ( t)       = ≡.cong ▹_ (Ind→prop σ t)
Ind→prop σ (t  t₁)    = ≡.cong₂ _∗_ (Ind→prop σ t) (Ind→prop σ t₁)
--Ind→prop σ (cast eq t) = ≡.cong (cast eq) (Ind→prop σ t)

prop→Ind' :  {Γ Δ} (σ : RenSub `Var Γ Δ) {τ} (t : Tm Γ τ)  IndRen σ t (subst σ t)
prop→Ind' σ (var x) = var x ≡.refl
prop→Ind' σ (abs t)     = abs (prop→Ind' (lifts σ) t)
prop→Ind' σ (app t u)   = app (prop→Ind' σ t) (prop→Ind' σ u)
prop→Ind' σ ( t)       =  (prop→Ind' σ t)
prop→Ind' σ (t  u)     = (prop→Ind' σ t)  (prop→Ind' σ u)
prop→Ind' σ (pair t u)  = pair (prop→Ind' σ t) (prop→Ind' σ u)
prop→Ind' σ (fst t)     = fst (prop→Ind' σ t)
prop→Ind' σ (snd t)     = snd (prop→Ind' σ t)
--prop→Ind' σ (cast eq t) = cast eq (prop→Ind' σ t)

prop→Ind :  {Γ Δ} (σ : RenSub `Var Γ Δ) {τ} {t : Tm Γ τ} {t' : Tm Δ τ}  subst σ t  t'  IndRen σ t t'
prop→Ind _ ≡.refl = prop→Ind' _ _

-- Identity substitution

ids :  {i vt Γ}  RenSub {i} vt Γ Γ
ids {vt = `Var} x = x
ids {vt = `Tm } x = var x

-- substitution composition

_•s_ :  {Γ₀ Γ₁ Γ₂}
         {n}{vt2 : VarTm n}(τ : RenSub vt2 Γ₁ Γ₂)
         {m}{vt1 : VarTm m}(σ : RenSub vt1 Γ₀ Γ₁)  RenSub (vt1 ∙VT vt2) Γ₀ Γ₂
_•s_ τ {vt1 = `Var} σ x = τ (σ x)
_•s_ τ {vt1 = `Tm } σ x = subst τ (σ x)

-- Term substitution

Subst : Cxt  Cxt  Set
Subst Γ Δ =  {a : Ty}  Var Γ a  Tm Δ a


-- Extending a substitution

_∷s_ :  {Γ Δ a}  Tm Γ a  Subst Δ Γ  Subst (a  Δ) Γ
(t ∷s σ) (zero) = t
(t ∷s σ) (suc x) = σ x

-- Substitution for 0th variable

sgs :  {Γ a}  Tm Γ a  Subst (a  Γ) Γ
sgs t = t ∷s ids

-- Substituting for the 0th variable [u/0]t

subst0 :  {Γ a b}  Tm Γ a  Tm (a  Γ) b  Tm Γ b
subst0 u = subst (sgs u)

-- Renamings

Ren : (Γ Δ : Cxt)  Set
Ren = RenSub `Var

_≤_  : (Γ Δ : Cxt)  Set
_≤_ Γ Δ = RenSub `Var Δ Γ

rename :  {Γ Δ : Cxt} {a : Ty} (η : Γ  Δ) (x : Tm Δ a)  Tm Γ a
rename = subst

-- Weakening renaming

weak : ∀{Γ a}  (a  Γ)  Γ
weak = suc

-- Weakening substitution

weaks : ∀{n}{vt : VarTm n}{a Γ Δ} (σ : RenSub vt Γ Δ)  RenSub vt (Γ) (a  Δ)
weaks {vt = `Var} σ x = suc (σ x)
weaks {vt = `Tm} σ x = rename suc (σ x)


-- Properties

module SubCong where

  _≡s_ :  {Γ Δ Γ' Δ'} {m n vt1 vt2}  (f : RenSub {m} vt1 Γ Δ)(g : RenSub {n} vt2 Γ' Δ')  Set
  f ≡s g = (∀ {a a'} {x : Var _ a}{x' : Var _ a'}  x ≅V x'  vt2tm _ (f {a} x) ≅T vt2tm _ (g x'))

  mutual
    subst-ext :  {Γ Γ' Δ Δ'} {m n vt1 vt2} {f : RenSub {m} vt1 Γ Δ}{g : RenSub {n} vt2 Γ' Δ'}  f ≡s g   {a} {t : Tm Γ a} {a'} {t' : Tm Γ' a'}
                 t ≅T t'  subst f t ≅T subst g t'
    subst-ext f≐g (var v) = f≐g v
    subst-ext {f = f} {g = g} f≐g (abs t)     = abs (subst-ext (lifts-ext {f = f} {g = g} f≐g) t)
    subst-ext f≐g (app t t₁)  = app (subst-ext f≐g t) (subst-ext f≐g t₁)
    subst-ext f≐g (pair t t₁) = pair (subst-ext f≐g t) (subst-ext f≐g t₁)
    subst-ext f≐g (fst t)     = fst (subst-ext f≐g t)
    subst-ext f≐g (snd t)     = snd (subst-ext f≐g t)
    subst-ext f≐g ( t)       = ▹_ (subst-ext f≐g t)
    subst-ext f≐g (t  t₁)    = _∗_ (subst-ext f≐g t) (subst-ext f≐g t₁)

    lifts-ext :  {Γ Δ b} {Γ' Δ' b'} {m n vt1 vt2} {f : RenSub {m} vt1 Γ Δ}{g : RenSub {n} vt2 Γ' Δ'}  f ≡s g  lifts {a = b} f ≡s lifts {a = b'} g
    lifts-ext {vt1 = `Var} {`Var} f≐g (zero) = var zero
    lifts-ext {vt1 = `Var} {`Var} {f} {g} f≐g (suc x) with f≐g x
    ... | var eq = var (suc eq)
    lifts-ext {vt1 = `Var} {`Tm} f≐g (zero) = var zero
    lifts-ext {vt1 = `Var} {`Tm} {f} {g} f≐g (suc {x' = x'} x) with g x' | f≐g x
    ... | ._ | var eq = var (suc eq)
    lifts-ext {vt1 = `Tm} {`Var} f≐g (zero) = var zero
    lifts-ext {vt1 = `Tm} {`Var} {f} {g} f≐g (suc {x = x} [x]) with f x | f≐g [x]
    ... | ._ | var eq = var (suc eq)
    lifts-ext {vt1 = `Tm} {`Tm} f≐g (zero) = var zero
    lifts-ext {vt1 = `Tm} {`Tm} f≐g (suc x) = subst-ext  x₂  var (suc x₂)) (f≐g x)


_≡s_ :  {Γ Δ} {m n vt1 vt2}  (f : RenSub {m} vt1 Γ Δ)(g : RenSub {n} vt2 Γ Δ)  Set
f ≡s g = (∀ {a} x  vt2tm _ (f {a} x)  vt2tm _ (g x))

mutual
  subst-ext :  {Γ Δ} {m n vt1 vt2} {f : RenSub {m} vt1 Γ Δ}{g : RenSub {n} vt2 Γ Δ}  f ≡s g   {a} (t : Tm Γ a)  subst f t  subst g t
  subst-ext f≐g (var v) = (f≐g v)
  subst-ext {f = f} {g = g} f≐g (abs t)     = ≡.cong abs (subst-ext (lifts-ext {f = f} {g = g} f≐g) t)
  subst-ext f≐g (app t t₁)  = ≡.cong₂ app (subst-ext f≐g t) (subst-ext f≐g t₁)
  subst-ext f≐g (pair t t₁) = ≡.cong₂ pair (subst-ext f≐g t) (subst-ext f≐g t₁)
  subst-ext f≐g (fst t)     = ≡.cong fst (subst-ext f≐g t)
  subst-ext f≐g (snd t)     = ≡.cong snd (subst-ext f≐g t)
  subst-ext f≐g ( t)       = ≡.cong ▹_ (subst-ext f≐g t)
  subst-ext f≐g (t  t₁)    = ≡.cong₂ _∗_ (subst-ext f≐g t) (subst-ext f≐g t₁)

  lifts-ext :  {Γ Δ b} {m n vt1 vt2} {f : RenSub {m} vt1 Γ Δ}{g : RenSub {n} vt2 Γ Δ}  f ≡s g  lifts {a = b} f ≡s lifts g
  lifts-ext {vt1 = `Var} {`Var} f≐g (zero) = ≡.refl
  lifts-ext {vt1 = `Var} {`Var} {f} {g} f≐g (suc x) with f x | g x | f≐g x
  lifts-ext {Γ} {Δ} {b} {._} {._} {`Var} {`Var} f≐g (suc x) | z | .z | ≡.refl = ≡.refl
  lifts-ext {vt1 = `Var} {`Tm} f≐g (zero) = ≡.refl
  lifts-ext {vt1 = `Var} {`Tm} f≐g (suc x) rewrite ≡.sym (f≐g x) = ≡.refl
  lifts-ext {vt1 = `Tm} {`Var} f≐g (zero) = ≡.refl
  lifts-ext {vt1 = `Tm} {`Var} f≐g (suc x) rewrite (f≐g x) = ≡.refl
  lifts-ext {vt1 = `Tm} {`Tm} f≐g (zero) = ≡.refl
  lifts-ext {vt1 = `Tm} {`Tm} f≐g (suc x) = ≡.cong (subst suc) (f≐g x)

mutual
  subst-∙ :  {Γ₀ Γ₁ Γ₂}
           {n}{vt2 : VarTm n}(τ : RenSub vt2 Γ₁ Γ₂)
           {m}{vt1 : VarTm m}(σ : RenSub vt1 Γ₀ Γ₁)   {a} (t : Tm Γ₀ a)  subst (τ •s σ) t  subst τ (subst σ t)
  subst-∙ τ {vt1 = `Var} σ (var x) = ≡.refl
  subst-∙ τ {vt1 = `Tm} σ (var x) = ≡.refl
  subst-∙ τ σ (abs t)     = ≡.cong abs (≡.trans (subst-ext (lifts-∙ τ σ) t) (subst-∙ (lifts τ) (lifts σ) t))
  subst-∙ τ σ (app t t₁)  = ≡.cong₂ app (subst-∙ τ σ t) (subst-∙ τ σ t₁)
  subst-∙ τ σ (pair t t₁) = ≡.cong₂ pair (subst-∙ τ σ t) (subst-∙ τ σ t₁)
  subst-∙ τ σ (fst t)     = ≡.cong fst (subst-∙ τ σ t)
  subst-∙ τ σ (snd t)     = ≡.cong snd (subst-∙ τ σ t)
  subst-∙ τ σ ( t)       = ≡.cong ▹_ (subst-∙ τ σ t)
  subst-∙ τ σ (t  t₁)    = ≡.cong₂ _∗_ (subst-∙ τ σ t) (subst-∙ τ σ t₁)

  lifts-∙ :  {Γ₀ Γ₁ Γ₂}
         {n}{vt2 : VarTm n}(τ : RenSub vt2 Γ₁ Γ₂)
         {m}{vt1 : VarTm m}(σ : RenSub vt1 Γ₀ Γ₁)   {a}  lifts {a = a} (τ •s σ) ≡s (lifts τ •s lifts σ)
  lifts-∙ {vt2 = `Var} τ {vt1 = `Var} σ (zero)    = ≡.refl
  lifts-∙ {vt2 = `Tm}  τ {vt1 = `Var} σ (zero)    = ≡.refl
  lifts-∙ {vt2 = `Var} τ {vt1 = `Var} σ (suc x) = ≡.refl
  lifts-∙ {vt2 = `Tm}  τ {vt1 = `Var} σ (suc x) = ≡.refl
  lifts-∙ {vt2 = `Var} τ {vt1 = `Tm}  σ (zero)    = ≡.refl
  lifts-∙ {vt2 = `Tm}  τ {vt1 = `Tm}  σ (zero)    = ≡.refl
  lifts-∙ {vt2 = `Var} τ {vt1 = `Tm}  σ (suc x) = ≡.trans (≡.sym (subst-∙ suc τ (σ x))) (subst-∙ (lifts τ) suc (σ x))
  lifts-∙ {vt2 = `Tm}  τ {vt1 = `Tm}  σ (suc x) = ≡.trans (≡.sym (subst-∙ suc τ (σ x))) (subst-∙ (lifts τ) suc (σ x))

mutual
  subst-id :  {m vt Γ a}  (t : Tm Γ a)  subst (ids {m} {vt}) t  t
  subst-id {vt = `Var} (var v) = ≡.refl
  subst-id {vt = `Tm}  (var v) = ≡.refl
  subst-id {m} {vt} {Γ} (abs t)     = ≡.cong abs (≡.trans (subst-ext {n = m} {vt2 = vt} (lifts-id {m} {vt}) t) (subst-id t))
  subst-id (app t t₁)  = ≡.cong₂ app (subst-id t) (subst-id t₁)
  subst-id (pair t t₁) = ≡.cong₂ pair (subst-id t) (subst-id t₁)
  subst-id (fst t)     = ≡.cong fst (subst-id t)
  subst-id (snd t)     = ≡.cong snd (subst-id t)
  subst-id ( t)       = ≡.cong ▹_ (subst-id t)
  subst-id (t  t₁)    = ≡.cong₂ _∗_ (subst-id t) (subst-id t₁)

  lifts-id :  {m vt Γ b}  lifts {a = b} (ids {m} {vt} {Γ = Γ}) ≡s ids {m} {vt} {Γ = b  Γ}
  lifts-id {vt = `Var} (zero)    = ≡.refl
  lifts-id {vt = `Var} (suc x) = ≡.refl
  lifts-id {vt = `Tm}  (zero)    = ≡.refl
  lifts-id {vt = `Tm}  (suc x) = ≡.refl

sgs-lifts :  {m vt Γ Δ a} {σ : RenSub {m} vt Γ Δ} {u : Tm Γ a}  (sgs (subst σ u) •s lifts σ) ≡s (σ •s sgs u)
sgs-lifts {vt = `Var} =  { {._} (zero)  ≡.refl ; (suc x)  ≡.refl })
sgs-lifts {vt = `Tm} {σ = σ} {u} =  { {._} (zero)  ≡.refl ; (suc x)  ≡.sym (≡.trans (≡.sym (subst-id (σ x)))
                                                                               (subst-∙ (sgs (subst σ u)) {vt1 = `Var} suc (σ x))) })
sgs-lifts-term :  {m vt Γ Δ a b} {σ : RenSub {m} vt Γ Δ} {u : Tm Γ a}{t : Tm (a  Γ) b}
                  subst (sgs (subst σ u)) (subst (lifts σ) t)  subst σ (subst (sgs u) t)
sgs-lifts-term {σ = σ} {u} {t} = (≡.trans (≡.sym (subst-∙ (sgs (subst σ u)) (lifts σ) t))
                                 (≡.trans (subst-ext sgs-lifts t)
                                          (subst-∙ σ (sgs u) t)))


renId :  {Γ a}{t : Tm Γ a}  rename id t  t
renId = subst-id _

contract :  {a Γ}  RenSub `Var (a  a  Γ) (a  Γ)
contract (zero)    = zero
contract (suc x) = x


contract-sgs :  {a Γ}  contract {a} {Γ} ≡s sgs (var zero)
contract-sgs (zero)  = ≡.refl
contract-sgs (suc x) = ≡.refl

sgs-weak₀ :  {Γ a} {u : Tm Γ a} {b} (x : Var Γ b)  sgs u (suc x)  var x
sgs-weak₀ x = ≡.refl

sgs-weak₁ :  {Γ a} {u : Tm Γ a}  (sgs u  suc) ≡s (ids {vt = `Tm})
sgs-weak₁ x = ≡.refl

sgs-weak :  {Γ a} {u : Tm Γ a}  (sgs u •s weak) ≡s (ids {vt = `Tm})
sgs-weak x = ≡.refl

cons-to-sgs :   {Γ Δ a} (u : Tm Δ a) (σ : Subst Γ Δ)
                (u ∷s σ) ≡s (sgs u •s lifts σ)
cons-to-sgs u σ (zero) = ≡.refl
cons-to-sgs u σ (suc x) = begin
    σ x                               ≡⟨ ≡.sym (subst-id (σ x)) 
    subst (ids {vt = `Tm}) (σ x)      ≡⟨ subst-ext  _  ≡.refl) (σ x) 
    subst (sgs u •s weak) (σ x)       ≡⟨ subst-∙ (sgs u) weak (σ x) 
    subst (sgs u) (subst suc (σ x))
  
  where open ≡-Reasoning