module linear.Usage.Erasure where open import Level open import Data.Nat hiding (_⊔_) open import Data.Vec as Vec hiding (_∷ʳ_) open import Data.List as List hiding (_∷ʳ_) open import Data.Product open import Function open import Relation.Binary.PropositionalEquality as PEq using (_≡_) open import linear.Type open import linear.Scope as Sc open import linear.Context as C open import linear.Context.Pointwise hiding (sym) open import linear.Usage as U open import linear.Usage.Consumption as UC hiding (divide) open import linear.Usage.Pointwise as UP hiding (sym) ⌊_⌋ : {n : ℕ} {γ : Context n} {Γ Δ : Usages γ} → Γ ⊆ Δ → Σ[ k ∈ ℕ ] Σ[ m ∈ Sc.Mergey k n ] Σ[ δ ∈ Context k ] Σ[ M ∈ C.Mergey m ] Σ[ 𝓜 ∈ U.Mergey M ] Σ[ eq ∈ Context[ _≡_ ] γ (δ C.⋈ M) ] coerce eq Γ ─ coerce eq Δ ≡ [[ δ ]] U.⋈ 𝓜 ─ ]] δ [[ U.⋈ 𝓜 ⌊ [] ⌋ = , , , , finish , [] , [] ⌊ ─∷ inc ⌋ = let (k , m , δ , M , 𝓜 , eq , usg) = ⌊ inc ⌋ in k , insert m , δ , insert _ M , insert (U.[ _ ]) 𝓜 , PEq.refl ∷ eq , (─∷ usg) ⌊ σ ∷ inc ⌋ = let (k , m , δ , M , 𝓜 , eq , usg) = ⌊ inc ⌋ in , , _ ∷ _ , , copy 𝓜 , PEq.refl ∷ eq , σ ∷ usg used : {n : ℕ} {γ : Context n} {Γ Δ : Usages γ} → Γ ⊆ Δ → List Type used [] = [] used (─∷ γ) = used γ used (σ ∷ γ) = σ ∷ used γ used-refl : {n : ℕ} {γ : Context n} {Γ : Usages γ} (inc : Γ ⊆ Γ) → used inc ≡ [] used-refl [] = PEq.refl used-refl (─∷ inc) = used-refl inc used-all : {n : ℕ} {γ : Context n} (pr : [[ γ ]] ⊆ ]] γ [[) → used pr ≡ toList γ used-all [] = PEq.refl used-all (σ ∷ γ) = PEq.cong (σ ∷_) (used-all γ) used-++ : {k l : ℕ} {γ : Context k} {δ : Context l} {Γ Γ′ : Usages γ} {Δ Δ′ : Usages δ} (incΓ : Γ ⊆ Γ′) (incΔ : Δ ⊆ Δ′) → used (incΓ UC.++ incΔ) ≡ used incΓ List.++ used incΔ used-++ [] incΔ = PEq.refl used-++ (─∷ incΓ) incΔ = used-++ incΓ incΔ used-++ (a ∷ incΓ) incΔ = PEq.cong (a ∷_) (used-++ incΓ incΔ) toList-++ : {k l : ℕ} (xs : Context k) (ys : Context l) → toList (xs Vec.++ ys) ≡ toList xs List.++ toList ys toList-++ [] ys = PEq.refl toList-++ (x ∷ xs) ys = PEq.cong (x ∷_) (toList-++ xs ys) infix 1 _++_≅_ infixr 20 _∷ˡ_ _∷ʳ_ data _++_≅_ {A : Set} : (xs ys zs : List A) → Set where [] : [] ++ [] ≅ [] _∷ˡ_ : (a : A) {xs ys zs : List A} (as : xs ++ ys ≅ zs) → a ∷ xs ++ ys ≅ a ∷ zs _∷ʳ_ : (a : A) {xs ys zs : List A} (as : xs ++ ys ≅ zs) → xs ++ a ∷ ys ≅ a ∷ zs sym : {A : Set} {xs ys zs : List A} → xs ++ ys ≅ zs → ys ++ xs ≅ zs sym [] = [] sym (x ∷ˡ xs) = x ∷ʳ sym xs sym (x ∷ʳ xs) = x ∷ˡ sym xs divide : {n : ℕ} {γ : Context n} {Γ Δ θ : Usages γ} (p : Γ ⊆ Δ) (q : Δ ⊆ θ) (pq : Γ ⊆ θ) → used p ++ used q ≅ used pq divide [] [] [] = [] divide (─∷ p) (─∷ q) (─∷ pq) = divide p q pq divide (─∷ p) (a ∷ q) (.a ∷ pq) = a ∷ʳ divide p q pq divide (a ∷ p) (─∷ q) (.a ∷ pq) = a ∷ˡ divide p q pq infixr 10 _++ʳ_ _++ˡ_ _++ʳ_ : {A : Set} {xs ys zs : List A} (ts : List A) (eq : xs ++ ys ≅ zs) → xs ++ ts List.++ ys ≅ ts List.++ zs [] ++ʳ eq = eq (t ∷ ts) ++ʳ eq = t ∷ʳ (ts ++ʳ eq) _++ˡ_ : {A : Set} {xs ys zs : List A} (ts : List A) (eq : xs ++ ys ≅ zs) → ts List.++ xs ++ ys ≅ ts List.++ zs [] ++ˡ eq = eq (t ∷ ts) ++ˡ eq = t ∷ˡ (ts ++ˡ eq) trivial : {A : Set} {xs ys : List A} → xs ++ ys ≅ xs List.++ ys trivial {xs = []} {[]} = [] trivial {xs = []} {y ∷ ys} = y ∷ʳ trivial trivial {xs = x ∷ xs} = x ∷ˡ trivial