{-# OPTIONS --safe #-}
open import Data.Nat using (ℕ)
module Data.StagedList (Item : ℕ → Set) where
open import Data.Nat using (ℕ; zero; suc; _≥‴_; _≤‴_; ≤‴-refl; ≤‴-step)
open import Data.Nat.Properties as ℕ
open import Function using (id; _∘_)
open import Relation.Nullary using (¬_)
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym; trans; cong; cong₂)
open import Data.Nat using (_+_; _∸_; _<_; s≤s; z≤n)
open import Data.Product as P using (∃-syntax; _×_; -,_; proj₁; proj₂)
open import Relation.Nullary.Decidable using (yes; no; toWitness; True)
variable
m n m′ n′ : ℕ
m≥n : m ≥‴ n
m′≥n : m′ ≥‴ n
≤‴-trans : n′ ≤‴ n → n ≤‴ m → n′ ≤‴ m
≤‴-trans ≤‴-refl n≤m = n≤m
≤‴-trans (≤‴-step sn′≤m) n≤m = ≤‴-step (≤‴-trans sn′≤m n≤m)
infixl 5 _,[_^_] _++_
data StagedList (n : ℕ) : Set where
∅ : StagedList n
_,[_^_] : StagedList n → Item m → (m≥n : m ≥‴ n) → StagedList n
_++_ : StagedList n → StagedList n → StagedList n
infixl 5 _↾
_↾ : StagedList n → StagedList (suc n)
∅ ↾ = ∅
xs ,[ x ^ ≤‴-refl ] ↾ = xs ↾
xs ,[ x ^ ≤‴-step m≥n ] ↾ = xs ↾ ,[ x ^ m≥n ]
xs ++ ys ↾ = (xs ↾) ++ (ys ↾)
infixl 5 _↾≥_
_↾≥_ : StagedList n → m ≥‴ n → StagedList m
xs ↾≥ ≤‴-refl = xs
xs ↾≥ ≤‴-step m≥sn = xs ↾ ↾≥ m≥sn
inject₁ : StagedList (suc n) → StagedList n
inject₁ ∅ = ∅
inject₁ (xs ,[ x ^ m≥sn ]) = inject₁ xs ,[ x ^ ≤‴-step m≥sn ]
inject₁ (xs ++ ys) = inject₁ xs ++ inject₁ ys
inject≥ : m ≥‴ n → StagedList m → StagedList n
inject≥ ≤‴-refl xs = xs
inject≥ (≤‴-step m≥sn) xs = inject₁ (inject≥ m≥sn xs)
infixl 5 _++♭_
_++♭_ : StagedList n → StagedList n → StagedList n
xs ++♭ ∅ = xs
xs ++♭ (ys ,[ y ^ m≥n ]) = xs ++♭ ys ,[ y ^ m≥n ]
xs ++♭ (ys ++ zs) = (xs ++♭ ys) ++♭ zs
private variable
xs ys zs : StagedList n
xs₁ xs₂ xs₃ : StagedList n
ys₁ ys₂ ys₃ : StagedList n
x x′ y z : Item n
↾≥-↾≥ : (m≥n : m ≥‴ n) (m′≥m : m′ ≥‴ m) → xs ↾≥ m≥n ↾≥ m′≥m ≡ xs ↾≥ (≤‴-trans m≥n m′≥m)
↾≥-↾≥ ≤‴-refl m′≥m = refl
↾≥-↾≥ (≤‴-step m≥n) m′≥m = ↾≥-↾≥ m≥n m′≥m
++-↾ : ∀ ys → (xs ++ ys) ↾ ≡ xs ↾ ++ (ys ↾)
++-↾ ys = refl
++-↾≥ : ∀ ys (m≥n : m ≥‴ n) → (xs ++ ys) ↾≥ m≥n ≡ xs ↾≥ m≥n ++ (ys ↾≥ m≥n)
++-↾≥ ys ≤‴-refl = refl
++-↾≥ ys (≤‴-step m≥sn) = ++-↾≥ (ys ↾) m≥sn
,-↾≥ : ∀ (m≥n : m ≥‴ n) → xs ,[ x ^ m≥n ] ↾≥ m≥n ≡ xs ↾≥ m≥n ,[ x ^ ≤‴-refl ]
,-↾≥ ≤‴-refl = refl
,-↾≥ (≤‴-step m≥n) = ,-↾≥ m≥n
inject₁-↾ : ∀ (xs : StagedList (suc n)) → (inject₁ xs) ↾ ≡ xs
inject₁-↾ ∅ = refl
inject₁-↾ (xs ,[ x ^ m≥n ]) = cong (_,[ x ^ m≥n ]) (inject₁-↾ xs)
inject₁-↾ (xs ++ ys) = cong₂ _++_ (inject₁-↾ xs) (inject₁-↾ ys)
++-inject₁-↾ : ∀ (ys : StagedList (suc n)) → xs ↾ ++ (inject₁ ys ↾) ≡ xs ↾ ++ ys
++-inject₁-↾ ys = cong (_ ++_) (inject₁-↾ ys)
inject₁-++ : ∀ (ys : StagedList (suc n)) → inject₁ (xs ++ ys) ≡ inject₁ xs ++ inject₁ ys
inject₁-++ ys = refl
inject≥-∅ : (m≥n : m ≥‴ n) → inject≥ m≥n ∅ ≡ ∅
inject≥-∅ ≤‴-refl = refl
inject≥-∅ (≤‴-step m≥n) = cong inject₁ (inject≥-∅ m≥n)
infix 4 _∋[_^_]
data _∋[_^_] : StagedList n → Item m → m ≥‴ n → Set where
Z : xs ,[ x ^ m≥n ] ∋[ x ^ m≥n ]
S : xs ∋[ x ^ m≥n ] → xs ,[ y ^ m′≥n ] ∋[ x ^ m≥n ]
L : xs ∋[ x ^ m≥n ] → xs ++ ys ∋[ x ^ m≥n ]
R : ys ∋[ y ^ m≥n ] → xs ++ ys ∋[ y ^ m≥n ]
∋-↾⁻ : ∀ {m≥sn} → xs ↾ ∋[ x ^ m≥sn ] → xs ∋[ x ^ ≤‴-step m≥sn ]
∋-↾⁻ {xs = xs ,[ x ^ ≤‴-refl ]} xs↾∋x = S (∋-↾⁻ xs↾∋x)
∋-↾⁻ {xs = xs ,[ x ^ ≤‴-step m≥n ]} Z = Z
∋-↾⁻ {xs = xs ,[ x ^ ≤‴-step m≥n ]} (S xs↾∋x) = S (∋-↾⁻ xs↾∋x)
∋-↾⁻ {xs = xs ++ ys} (L xs↾∋x) = L (∋-↾⁻ xs↾∋x)
∋-↾⁻ {xs = xs ++ ys} (R ys↾∋y) = R (∋-↾⁻ ys↾∋y)
∋-↾⁺ : ∀ {m≥sn} → xs ∋[ x ^ ≤‴-step m≥sn ] → xs ↾ ∋[ x ^ m≥sn ]
∋-↾⁺ Z = Z
∋-↾⁺ (S {m′≥n = ≤‴-refl} xs∋x) = ∋-↾⁺ xs∋x
∋-↾⁺ (S {m′≥n = ≤‴-step m′≥n} xs∋x) = S (∋-↾⁺ xs∋x)
∋-↾⁺ (L xs∋x) = L (∋-↾⁺ xs∋x)
∋-↾⁺ (R ys∋y) = R (∋-↾⁺ ys∋y)
∋-↾≥⁻ : ∀ n≥n′ → xs ↾≥ n≥n′ ∋[ x ^ m≥n ] → xs ∋[ x ^ ≤‴-trans n≥n′ m≥n ]
∋-↾≥⁻ ≤‴-refl = id
∋-↾≥⁻ (≤‴-step n≥n′) = ∋-↾⁻ ∘ ∋-↾≥⁻ n≥n′
∋-↾≥⁺ : ∀ m≥n → xs ∋[ x ^ m≥n ] → xs ↾≥ m≥n ∋[ x ^ ≤‴-refl ]
∋-↾≥⁺ ≤‴-refl = id
∋-↾≥⁺ (≤‴-step m≥n) = ∋-↾≥⁺ m≥n ∘ ∋-↾⁺
∋-inject₁⁺ : xs ∋[ x ^ m≥n ] → inject₁ xs ∋[ x ^ ≤‴-step m≥n ]
∋-inject₁⁺ Z = Z
∋-inject₁⁺ (S xs∋x) = S (∋-inject₁⁺ xs∋x)
∋-inject₁⁺ (L xs∋x) = L (∋-inject₁⁺ xs∋x)
∋-inject₁⁺ (R ys∋y) = R (∋-inject₁⁺ ys∋y)
∋-inject₁⁻ : inject₁ xs ∋[ x ^ ≤‴-step m≥n ] → xs ∋[ x ^ m≥n ]
∋-inject₁⁻ {xs = xs ,[ _ ^ _ ]} Z = Z
∋-inject₁⁻ {xs = xs ,[ _ ^ _ ]} (S xs∋x) = S (∋-inject₁⁻ xs∋x)
∋-inject₁⁻ {xs = xs ++ ys} (L xs∋x) = L (∋-inject₁⁻ xs∋x)
∋-inject₁⁻ {xs = xs ++ ys} (R ys∋y) = R (∋-inject₁⁻ ys∋y)
∋-inject≥⁺ : (n≥n′ : n ≥‴ n′) → xs ∋[ x ^ m≥n ] → inject≥ n≥n′ xs ∋[ x ^ ≤‴-trans n≥n′ m≥n ]
∋-inject≥⁺ ≤‴-refl = id
∋-inject≥⁺ (≤‴-step n≥sn′) = ∋-inject₁⁺ ∘ ∋-inject≥⁺ n≥sn′
∋-++-, : xs ++ ys ,[ y ^ m≥n ] ∋[ z ^ m′≥n ] → xs ++ (ys ,[ y ^ m≥n ]) ∋[ z ^ m′≥n ]
∋-++-, Z = R Z
∋-++-, (S (L xs∋z)) = L xs∋z
∋-++-, (S (R ys∋z)) = R (S ys∋z)
∋-++-,⁻¹ : xs ++ (ys ,[ y ^ m≥n ]) ∋[ z ^ m′≥n ] → xs ++ ys ,[ y ^ m≥n ] ∋[ z ^ m′≥n ]
∋-++-,⁻¹ (L xs∋z) = S (L xs∋z)
∋-++-,⁻¹ (R (S ys∋z)) = S (R ys∋z)
∋-++-,⁻¹ (R Z) = Z
∋-++-++ : xs ++ ys ++ zs ∋[ z ^ m≥n ] → xs ++ (ys ++ zs) ∋[ z ^ m≥n ]
∋-++-++ (L (L xs∋z)) = L xs∋z
∋-++-++ (L (R ys∋z)) = R (L ys∋z)
∋-++-++ (R zs∋z) = R (R zs∋z)
∋-++-++⁻¹ : xs ++ (ys ++ zs) ∋[ z ^ m≥n ] → xs ++ ys ++ zs ∋[ z ^ m≥n ]
∋-++-++⁻¹ (L xs∋z) = L (L xs∋z)
∋-++-++⁻¹ (R (L ys∋z)) = L (R ys∋z)
∋-++-++⁻¹ (R (R zs∋z)) = R zs∋z
inject₁-∌-refl : ¬ (inject₁ xs ∋[ x ^ ≤‴-refl ])
inject₁-∌-refl {xs = xs ,[ _ ^ _ ]} (S xs∋x) = inject₁-∌-refl xs∋x
inject₁-∌-refl {xs = xs ++ ys} (L xs∋x) = inject₁-∌-refl xs∋x
inject₁-∌-refl {xs = xs ++ ys} (R ys∋y) = inject₁-∌-refl ys∋y
∋-castˡ : xs ≡ ys → xs ∋[ x ^ m≥n ] → ys ∋[ x ^ m≥n ]
∋-castˡ refl x = x
∋-castˡ-Z : ∀ (eq : xs ≡ ys) → ∋-castˡ (cong (_,[ x ^ m≥n ]) eq) Z ≡ Z
∋-castˡ-Z refl = refl
∋-castˡ-S : ∀ (eq : xs ≡ ys) (xs∋x : xs ∋[ x ^ m≥n ]) → ∋-castˡ (cong (_,[ x′ ^ m′≥n ]) eq) (S xs∋x) ≡ S (∋-castˡ eq xs∋x)
∋-castˡ-S refl xs∋x = refl
∋-castˡ-L : ∀ (eq₁ : xs₁ ≡ ys₁) (eq₂ : xs₂ ≡ ys₂) (xs∋x : xs₁ ∋[ x ^ m≥n ]) → ∋-castˡ (cong₂ (_++_) eq₁ eq₂) (L xs∋x) ≡ L (∋-castˡ eq₁ xs∋x)
∋-castˡ-L refl refl xs∋x = refl
∋-castˡ-R : ∀ (eq₁ : xs₁ ≡ ys₁) (eq₂ : xs₂ ≡ ys₂) (xs∋x : xs₂ ∋[ x ^ m≥n ]) → ∋-castˡ (cong₂ (_++_) eq₁ eq₂) (R xs∋x) ≡ R (∋-castˡ eq₂ xs∋x)
∋-castˡ-R refl refl xs∋x = refl
Rename : StagedList n → StagedList n → Set
Rename xs ys = ∀ {m} {x} {m≥n : m ≥‴ _} → xs ∋[ x ^ m≥n ] → ys ∋[ x ^ m≥n ]
ext : Rename xs ys → Rename (xs ,[ z ^ m≥n ]) (ys ,[ z ^ m≥n ])
ext ρ Z = Z
ext ρ (S xs∋x) = S (ρ xs∋x)
ext++ : ∀ zs → Rename xs ys → Rename (xs ++ zs) (ys ++ zs)
ext++ zs ρ (L xs∋x) = L (ρ xs∋x)
ext++ zs ρ (R zs∋z) = R (zs∋z)
ext++ˡ : ∀ zs → Rename xs ys → Rename (zs ++ xs) (zs ++ ys)
ext++ˡ zs ρ (L zs∋z) = L (zs∋z)
ext++ˡ zs ρ (R xs∋x) = R (ρ xs∋x)
ext↾ : Rename xs ys → Rename (xs ↾) (ys ↾)
ext↾ ρ = ∋-↾⁺ ∘ ρ ∘ ∋-↾⁻
ext↾≥ : ∀ (m≥n : m ≥‴ n) → Rename xs ys → Rename (xs ↾≥ m≥n) (ys ↾≥ m≥n)
ext↾≥ ≤‴-refl ρ = ρ
ext↾≥ (≤‴-step m≥sn) ρ = ext↾≥ m≥sn (ext↾ ρ)
ext↾≥++ : ∀ (m≥n : m ≥‴ n) zs → Rename xs ys → Rename (xs ↾≥ m≥n ++ zs) (ys ↾≥ m≥n ++ zs)
ext↾≥++ m≥n zs = ext++ zs ∘ ext↾≥ m≥n
Rename-inject₁⁻ : ∀ {xs ys : StagedList (suc n)} → Rename (inject₁ xs) (inject₁ ys) → Rename xs ys
Rename-inject₁⁻ ρ = ∋-inject₁⁻ ∘ ρ ∘ ∋-inject₁⁺
↾-inject₁ : (xs : StagedList n) → Rename (inject₁ (xs ↾)) xs
↾-inject₁ (xs ,[ x ^ ≤‴-refl ]) = S ∘ ↾-inject₁ xs
↾-inject₁ (xs ,[ x ^ ≤‴-step m≥n ]) Z = Z
↾-inject₁ (xs ,[ x ^ ≤‴-step m≥n ]) (S xs∋x) = S (↾-inject₁ xs xs∋x)
↾-inject₁ (xs ++ ys) (L xs∋x) = L (↾-inject₁ xs xs∋x)
↾-inject₁ (xs ++ ys) (R ys∋y) = R (↾-inject₁ ys ys∋y)
∋-++♭⁺ : ∀ ys → xs ++ ys ∋[ z ^ m≥n ] → xs ++♭ ys ∋[ z ^ m≥n ]
∋-++♭⁺ ∅ (L x) = x
∋-++♭⁺ (ys ,[ x ^ m≥n ]) = ext (∋-++♭⁺ ys) ∘ ∋-++-,⁻¹
∋-++♭⁺ (ys ++ ys′) = ∋-++♭⁺ ys′ ∘ ext++ ys′ (∋-++♭⁺ ys) ∘ ∋-++-++⁻¹
∋-++♭⁻ : ∀ ys → xs ++♭ ys ∋[ z ^ m≥n ] → xs ++ ys ∋[ z ^ m≥n ]
∋-++♭⁻ ∅ = L
∋-++♭⁻ (ys ,[ y ^ m≥n ]) = ∋-++-, ∘ ext (∋-++♭⁻ ys)
∋-++♭⁻ (ys ++ ys′) = ∋-++-++ ∘ ext++ ys′ (∋-++♭⁻ ys) ∘ ∋-++♭⁻ ys′
module _ {B : ∀ (m : ℕ) (x : Item m) (m≥n : m ≥‴ n) → Set} where
private variable
f g h : ∀ {m} {x} {m≥n : m ≥‴ _} → xs ∋[ x ^ m≥n ] → B m x m≥n
infix 4 _≗_
_≗_ : (f g : ∀ {m} {x} {m≥n : m ≥‴ _} → xs ∋[ x ^ m≥n ] → B m x m≥n) → Set
_≗_ {xs = xs} ρ ρ′ = ∀ {m} {x} {m≥n : m ≥‴ _} (xs∋x : xs ∋[ x ^ m≥n ]) → ρ xs∋x ≡ ρ′ xs∋x
≗-refl : f ≗ f
≗-refl _ = refl
≗-sym : f ≗ g → g ≗ f
≗-sym f≗g xs∋x = sym (f≗g xs∋x)
≗-trans : f ≗ g → g ≗ h → f ≗ h
≗-trans f≗g g≗h xs∋x = trans (f≗g xs∋x) (g≗h xs∋x)
∋-↾⁻-∋-↾⁺ : (xs∋x : xs ∋[ x ^ ≤‴-step m≥n ]) → ∋-↾⁻ (∋-↾⁺ xs∋x) ≡ xs∋x
∋-↾⁻-∋-↾⁺ Z = refl
∋-↾⁻-∋-↾⁺ (S {m′≥n = ≤‴-refl} xs∋x) = cong S (∋-↾⁻-∋-↾⁺ xs∋x)
∋-↾⁻-∋-↾⁺ (S {m′≥n = ≤‴-step _} xs∋x) = cong S (∋-↾⁻-∋-↾⁺ xs∋x)
∋-↾⁻-∋-↾⁺ (L xs∋x) = cong L (∋-↾⁻-∋-↾⁺ xs∋x)
∋-↾⁻-∋-↾⁺ (R xs∋x) = cong R (∋-↾⁻-∋-↾⁺ xs∋x)
∋-↾⁺-∋-↾⁻ : (xs∋x : xs ↾ ∋[ x ^ m≥n ]) → ∋-↾⁺ (∋-↾⁻ {xs = xs} xs∋x) ≡ xs∋x
∋-↾⁺-∋-↾⁻ {xs = xs ,[ _ ^ ≤‴-refl ]} xs∋x = ∋-↾⁺-∋-↾⁻ {xs = xs} xs∋x
∋-↾⁺-∋-↾⁻ {xs = xs ,[ x ^ ≤‴-step m≥n ]} Z = refl
∋-↾⁺-∋-↾⁻ {xs = xs ,[ _ ^ ≤‴-step _ ]} (S xs∋x) = cong S (∋-↾⁺-∋-↾⁻ {xs = xs} xs∋x)
∋-↾⁺-∋-↾⁻ {xs = xs ++ _} (L x) = cong L (∋-↾⁺-∋-↾⁻ {xs = xs} x)
∋-↾⁺-∋-↾⁻ {xs = _ ++ xs} (R x) = cong R (∋-↾⁺-∋-↾⁻ {xs = xs} x)
∋-inject₁⁻-∋-inject₁⁺ : (xs∋x : xs ∋[ x ^ m≥n ]) → ∋-inject₁⁻ (∋-inject₁⁺ xs∋x) ≡ xs∋x
∋-inject₁⁻-∋-inject₁⁺ Z = refl
∋-inject₁⁻-∋-inject₁⁺ (S xs∋x) = cong S (∋-inject₁⁻-∋-inject₁⁺ xs∋x)
∋-inject₁⁻-∋-inject₁⁺ (L xs∋x) = cong L (∋-inject₁⁻-∋-inject₁⁺ xs∋x)
∋-inject₁⁻-∋-inject₁⁺ (R xs∋x) = cong R (∋-inject₁⁻-∋-inject₁⁺ xs∋x)
∋-inject₁⁺-∋-inject₁⁻ : ∀ {xs : StagedList (suc n)} (xs∋x : inject₁ xs ∋[ x ^ ≤‴-step m≥n ]) → ∋-inject₁⁺ (∋-inject₁⁻ xs∋x) ≡ xs∋x
∋-inject₁⁺-∋-inject₁⁻ {xs = xs ,[ x ^ m≥n ]} Z = refl
∋-inject₁⁺-∋-inject₁⁻ {xs = xs ,[ x ^ m≥n ]} (S xs∋x) = cong S (∋-inject₁⁺-∋-inject₁⁻ xs∋x)
∋-inject₁⁺-∋-inject₁⁻ {xs = xs ++ xs₁} (L xs∋x) = cong L (∋-inject₁⁺-∋-inject₁⁻ xs∋x)
∋-inject₁⁺-∋-inject₁⁻ {xs = xs ++ xs₁} (R xs∋x) = cong R (∋-inject₁⁺-∋-inject₁⁻ xs∋x)
∋-inject₁⁻-∋-↾⁻-∋-↾⁺-∋-inject₁⁺ : ∀ (xs∋x : xs ∋[ x ^ m≥n ]) → ∋-inject₁⁻ (∋-↾⁻ (∋-↾⁺ (∋-inject₁⁺ xs∋x))) ≡ xs∋x
∋-inject₁⁻-∋-↾⁻-∋-↾⁺-∋-inject₁⁺ xs∋x = trans (cong ∋-inject₁⁻ (∋-↾⁻-∋-↾⁺ (∋-inject₁⁺ xs∋x))) (∋-inject₁⁻-∋-inject₁⁺ xs∋x)
∋-↾⁺-∋-inject₁⁺-∋-inject₁⁻-∋-↾⁻ : ∀ {xs : StagedList (suc n)} (xs∋x : inject₁ xs ↾ ∋[ x ^ m≥n ]) → ∋-↾⁺ (∋-inject₁⁺ {xs = xs} (∋-inject₁⁻ (∋-↾⁻ xs∋x))) ≡ xs∋x
∋-↾⁺-∋-inject₁⁺-∋-inject₁⁻-∋-↾⁻ {xs = xs} xs∋x = trans (cong ∋-↾⁺ (∋-inject₁⁺-∋-inject₁⁻ {xs = xs} (∋-↾⁻ xs∋x))) (∋-↾⁺-∋-↾⁻ {xs = inject₁ xs} xs∋x)
ext-resp-≗ : {ρ ρ′ : Rename xs ys} → ρ ≗ ρ′ → ext {z = z} {m≥n = m≥n} ρ ≗ ext ρ′
ext-resp-≗ ρ≗ρ′ Z = refl
ext-resp-≗ ρ≗ρ′ (S _) = cong S (ρ≗ρ′ _)
ext++-resp-≗ : ∀ zs → {ρ ρ′ : Rename xs ys} → ρ ≗ ρ′ → ext++ zs ρ ≗ ext++ zs ρ′
ext++-resp-≗ zs ρ≗ρ′ (L _) = cong L (ρ≗ρ′ _)
ext++-resp-≗ zs ρ≗ρ′ (R _) = refl
ext↾-resp-≗ : {ρ ρ′ : Rename xs ys} → ρ ≗ ρ′ → ext↾ ρ ≗ ext↾ ρ′
ext↾-resp-≗ ρ≗ρ′ = cong ∋-↾⁺ ∘ ρ≗ρ′ ∘ ∋-↾⁻
ext↾≥-resp-≗ : ∀ (m≥n : m ≥‴ n) → {ρ ρ′ : Rename xs ys} → ρ ≗ ρ′ → ext↾≥ m≥n ρ ≗ ext↾≥ m≥n ρ′
ext↾≥-resp-≗ ≤‴-refl ρ≗ρ′ = ρ≗ρ′
ext↾≥-resp-≗ (≤‴-step m≥n) ρ≗ρ′ = ext↾≥-resp-≗ m≥n (ext↾-resp-≗ ρ≗ρ′)
ext-id : ext {xs = xs} {z = z} {m≥n = m≥n} id ≗ id
ext-id Z = refl
ext-id (S _) = refl
ext-∘ : (ρ′ : Rename xs₂ xs₃) → (ρ : Rename xs₁ xs₂) → ext {z = z} {m≥n = m≥n} (ρ′ ∘ ρ) ≗ ext ρ′ ∘ ext ρ
ext-∘ ρ′ ρ Z = refl
ext-∘ ρ′ ρ (S _) = refl
ext++-id : ∀ (zs : StagedList n) → ext++ {xs = xs} zs id ≗ id
ext++-id zs (L _) = refl
ext++-id zs (R _) = refl
ext++-∘ : (zs : StagedList n) → (ρ′ : Rename xs₂ xs₃) → (ρ : Rename xs₁ xs₂) → ext++ zs (ρ′ ∘ ρ) ≗ ext++ zs ρ′ ∘ ext++ zs ρ
ext++-∘ zs ρ′ ρ (L _) = refl
ext++-∘ zs ρ′ ρ (R _) = refl
ext↾-id : ext↾ {xs = xs} id ≗ id
ext↾-id {xs = xs ,[ x ^ ≤‴-refl ]} xs∋x = ext↾-id {xs = xs} xs∋x
ext↾-id {xs = xs ,[ x ^ ≤‴-step m≥n ]} Z = refl
ext↾-id {xs = xs ,[ x ^ ≤‴-step m≥n ]} (S xs∋x) = cong S (ext↾-id {xs = xs} xs∋x)
ext↾-id {xs = xs ++ ys} (L xs∋x) = cong L (ext↾-id {xs = xs} xs∋x)
ext↾-id {xs = xs ++ ys} (R ys∋x) = cong R (ext↾-id {xs = ys} ys∋x)
ext↾-∘ : (ρ′ : Rename xs₂ xs₃) → (ρ : Rename xs₁ xs₂) → ext↾ (ρ′ ∘ ρ) ≗ ext↾ ρ′ ∘ ext↾ ρ
ext↾-∘ {xs₁ = xs₁ ,[ x ^ m≥n ]} ρ′ ρ xs∋x = cong (∋-↾⁺ ∘ ρ′) (sym (∋-↾⁻-∋-↾⁺ _))
ext↾-∘ {xs₁ = xs ++ ys} ρ′ ρ (L xs∋x) = cong (∋-↾⁺ ∘ ρ′) ((sym (∋-↾⁻-∋-↾⁺ _)))
ext↾-∘ {xs₁ = xs ++ ys} ρ′ ρ (R ys∋x) = cong (∋-↾⁺ ∘ ρ′) ((sym (∋-↾⁻-∋-↾⁺ _)))
ext↾-∋-↾⁺ : (ρ : Rename xs ys) (xs∋x : xs ∋[ x ^ ≤‴-step m≥n ]) → ext↾ ρ (∋-↾⁺ xs∋x) ≡ ∋-↾⁺ (ρ xs∋x)
ext↾-∋-↾⁺ ρ Z = refl
ext↾-∋-↾⁺ ρ (S {m′≥n = ≤‴-refl} xs∋x) = cong (∋-↾⁺ ∘ ρ ∘ S) (∋-↾⁻-∋-↾⁺ xs∋x)
ext↾-∋-↾⁺ ρ (S {m′≥n = ≤‴-step _} xs∋x) = cong (∋-↾⁺ ∘ ρ ∘ S) (∋-↾⁻-∋-↾⁺ xs∋x)
ext↾-∋-↾⁺ ρ (L xs∋x) = ext↾-∋-↾⁺ (ρ ∘ L) xs∋x
ext↾-∋-↾⁺ ρ (R xs∋x) = ext↾-∋-↾⁺ (ρ ∘ R) xs∋x
ext↾≥-id : ∀ (m≥n : m ≥‴ n) → ext↾≥ {xs = xs} m≥n id ≗ id
ext↾≥-id ≤‴-refl = ≗-refl {f = id}
ext↾≥-id {xs = xs} (≤‴-step m≥n) = ≗-trans (ext↾≥-resp-≗ m≥n (ext↾-id {xs = xs})) (ext↾≥-id m≥n)
ext↾≥-∘ : ∀ (m≥n : m ≥‴ n) → (ρ′ : Rename xs₂ xs₃) → (ρ : Rename xs₁ xs₂) → ext↾≥ m≥n (ρ′ ∘ ρ) ≗ ext↾≥ m≥n ρ′ ∘ ext↾≥ m≥n ρ
ext↾≥-∘ ≤‴-refl ρ′ ρ = ≗-refl {f = (ρ′ ∘ ρ)}
ext↾≥-∘ (≤‴-step m≥n) ρ′ ρ = ≗-trans ((ext↾≥-resp-≗ m≥n (ext↾-∘ ρ′ ρ))) (ext↾≥-∘ m≥n (ext↾ ρ′) (ext↾ ρ))
Rename-inject₁⁻-id : ∀ {xs : StagedList (suc n)} → Rename-inject₁⁻ {xs = xs} id ≗ id
Rename-inject₁⁻-id Z = refl
Rename-inject₁⁻-id (S x) = cong S (Rename-inject₁⁻-id x)
Rename-inject₁⁻-id (L x) = cong L (Rename-inject₁⁻-id x)
Rename-inject₁⁻-id (R x) = cong R (Rename-inject₁⁻-id x)
Rename-inject₁⁻-R : ∀ {xs ys : StagedList (suc n)} → Rename-inject₁⁻ {xs = ys} (R {xs = inject₁ xs}) ≗ R
Rename-inject₁⁻-R Z = refl
Rename-inject₁⁻-R (S x) = cong (R ∘ S) (Rename-inject₁⁻-id x)
Rename-inject₁⁻-R (L x) = cong (R ∘ L) (Rename-inject₁⁻-id x)
Rename-inject₁⁻-R (R x) = cong (R ∘ R) (Rename-inject₁⁻-id x)
Rename-inject₁⁻-L : ∀ {xs ys : StagedList (suc n)} → Rename-inject₁⁻ {xs = xs} (L {ys = inject₁ ys}) ≗ L
Rename-inject₁⁻-L Z = refl
Rename-inject₁⁻-L (S x) = cong (L ∘ S) (Rename-inject₁⁻-id x)
Rename-inject₁⁻-L (L x) = cong (L ∘ L) (Rename-inject₁⁻-id x)
Rename-inject₁⁻-L (R x) = cong (L ∘ R) (Rename-inject₁⁻-id x)
length : StagedList n → ℕ
length ∅ = zero
length (xs ,[ _ ^ _ ]) = suc (length xs)
length (xs ++ ys) = length ys + length xs
lookupℕ : {xs : StagedList n} → {k : ℕ} → (p : k < length xs) → ∃[ m ] (Item m × m ≥‴ n)
lookupℕ {xs = xs ,[ x ^ m≥n ]} {k = zero} (s≤s z≤n) = -, x P., m≥n
lookupℕ {xs = xs ,[ _ ^ _ ]} {k = suc k} (s≤s p) = lookupℕ {xs = xs} p
lookupℕ {xs = xs ++ ys} {k = k} p with k ℕ.<? (length ys)
... | yes p′ = lookupℕ {xs = ys} p′
... | no k≮ny = lookupℕ {xs = xs} {k = k ∸ length ys} (ℕ.+-cancelʳ-< (length ys) _ _ (
begin
suc (k ∸ length ys + length ys)
≡⟨ cong suc (m∸n+n≡m (≮⇒≥ k≮ny)) ⟩
suc k
≤⟨ p ⟩
length ys + length xs
≡⟨ ℕ.+-comm (length ys) (length xs) ⟩
length xs + length ys
∎))
where open ℕ.≤-Reasoning
countℕ : {xs : StagedList n} → {k : ℕ} → (p : k < length xs) → xs ∋[ lookupℕ {xs = xs} p .proj₂ .proj₁ ^ lookupℕ {xs = xs} p .proj₂ .proj₂ ]
countℕ {xs = xs ,[ x ^ m≥n ]} {k = zero} (s≤s z≤n) = Z
countℕ {xs = xs ,[ x ^ m≥n ]} {k = suc k} (s≤s p) = S (countℕ p)
countℕ {xs = xs ++ ys} {k = k} p with k ℕ.<? (length ys)
... | yes p′ = R (countℕ {xs = ys} _)
... | no _ = L (countℕ {xs = xs} _)
# : ∀ {xs : StagedList n}
→ (k : ℕ)
→ {k∈Γ : True (k <? length xs)}
→ xs ∋[ lookupℕ {xs = xs} (toWitness k∈Γ) .proj₂ .proj₁ ^ lookupℕ {xs = xs} (toWitness k∈Γ) .proj₂ .proj₂ ]
# n {k∈Γ} = countℕ (toWitness k∈Γ)