module linear.Mix where open import Data.Fin as F open import Data.Sum as Sum open import Data.Product as Prod open import Function open import Relation.Binary.PropositionalEquality as Eq hiding ([_]) open import linear.Context as C open import linear.Context.Pointwise as CP open import linear.Context.Mix open import linear.Usage as U hiding ([_]) open import linear.Usage.Pointwise as UP open import linear.Usage.Mix open import linear.Typing.Extensional Mix : ∀ {T} → Typing T → Set Mix {T} 𝓣 = ∀ {l m n o} {γ : Context l} {δ : Context m} {θ : Context n} {ξ : Context o} {Γ₁ Γ₂ Δ₁ Δ₂ Γ Γ′ Δ Δ′ t σ} {p : γ ++ δ ≅ θ} {q : γ ++ δ ≅ ξ} → [ p ] Γ₁ ++ Γ₂ ≅ Γ → [ p ] Δ₁ ++ Δ₂ ≅ Δ → [ q ] Γ₁ ++ Γ₂ ≅ Γ′ → [ q ] Δ₁ ++ Δ₂ ≅ Δ′ → 𝓣 Γ t σ Δ → ∃ λ t → 𝓣 Γ′ t σ Δ′ splitFin : ∀ {m n p} {γ : Context m} {δ : Context n} {θ : Context p} {Γ₁ Γ₂ Δ₁ Δ₂ Γ Δ k σ} (p : γ ++ δ ≅ θ) → [ p ] Γ₁ ++ Γ₂ ≅ Γ → [ p ] Δ₁ ++ Δ₂ ≅ Δ → Γ ⊢ k ∈[ σ ]⊠ Δ → (∃ λ k → Γ₁ ⊢ k ∈[ σ ]⊠ Δ₁ × Γ₂ ≡ Δ₂) ⊎ (∃ λ k → Γ₂ ⊢ k ∈[ σ ]⊠ Δ₂ × Γ₁ ≡ Δ₁) splitFin [] [] [] () splitFin (σ ∷ˡ p) (_ ∷ˡ eq₁) (_ ∷ˡ eq₂) z rewrite proj₁ (≅-inj p eq₁ eq₂) = inj₁ (, z , proj₂ (≅-inj p eq₁ eq₂)) splitFin (σ ∷ʳ p) (_ ∷ʳ eq₁) (_ ∷ʳ eq₂) z rewrite proj₂ (≅-inj p eq₁ eq₂) = inj₂ (, z , proj₁ (≅-inj p eq₁ eq₂)) splitFin (σ ∷ˡ p) (u ∷ˡ eq₁) (.u ∷ˡ eq₂) (s K) = Sum.map (Prod.map F.suc (Prod.map s_ id)) (Prod.map id (Prod.map id (cong (u ∷_)))) $ splitFin p eq₁ eq₂ K splitFin (σ ∷ʳ p) (u ∷ʳ eq₁) (.u ∷ʳ eq₂) (s K) = Sum.map (Prod.map id (Prod.map id (cong (u ∷_)))) (Prod.map F.suc (Prod.map s_ id)) $ splitFin p eq₁ eq₂ K unsplitContext : ∀ {m n p} {γ : Context m} {δ : Context n} {θ : Context p} (p : γ ++ δ ≅ θ) → ∃ λ (mM₁ : ∃ C.Mergey) → ∃ λ (mM₂ : ∃ C.Mergey) → Context[ _≡_ ] θ (γ C.⋈ proj₂ mM₁) × Context[ _≡_ ] θ (δ C.⋈ proj₂ mM₂) unsplitContext [] = (, finish) , (, finish) , ([] , []) unsplitContext (σ ∷ˡ p) = let ((_ , M₁) , (_ , M₂) , eq₁ , eq₂) = unsplitContext p in (, copy M₁) , (, insert σ M₂) , Eq.refl ∷ eq₁ , Eq.refl ∷ eq₂ unsplitContext (σ ∷ʳ p) = let ((m₁ , M₁) , (m₂ , M₂) , eq₁ , eq₂) = unsplitContext p in (, insert σ M₁) , (, copy M₂) , Eq.refl ∷ eq₁ , Eq.refl ∷ eq₂ unsplitUsages₁ : ∀ {m n p} {γ : Context m} {δ : Context n} {θ : Context p} (p : γ ++ δ ≅ θ) (Δ : Usages δ) → let ((_ , M₁) , _) = unsplitContext p in U.Mergey M₁ unsplitUsages₁ [] Δ = finish unsplitUsages₁ (a ∷ˡ p) Δ = copy (unsplitUsages₁ p Δ) unsplitUsages₁ (a ∷ʳ p) (A ∷ Δ) = insert A (unsplitUsages₁ p Δ) unsplitUsages₁-eq : ∀ {m n p} {γ : Context m} {δ : Context n} {θ : Context p} {p : γ ++ δ ≅ θ} {Δ : Usages δ} → let ((_ , M₁) , _ , eq₁ , _) = unsplitContext p in ∀ {Γ Θ} → [ p ] Γ ++ Δ ≅ Θ → Usages[ _≡_ , UsageEq ] eq₁ Θ (Γ U.⋈ unsplitUsages₁ p Δ) unsplitUsages₁-eq [] = [] unsplitUsages₁-eq (S ∷ˡ eq) = Eq.refl ∷ (unsplitUsages₁-eq eq) unsplitUsages₁-eq (S ∷ʳ eq) = Eq.refl ∷ (unsplitUsages₁-eq eq) unsplitUsages₂ : ∀ {m n p} {γ : Context m} {δ : Context n} {θ : Context p} (p : γ ++ δ ≅ θ) (Γ : Usages γ) → let (_ , (_ , M₂) , _) = unsplitContext p in U.Mergey M₂ unsplitUsages₂ [] Γ = finish unsplitUsages₂ (a ∷ˡ p) (A ∷ Γ) = insert A (unsplitUsages₂ p Γ) unsplitUsages₂ (a ∷ʳ p) Γ = copy (unsplitUsages₂ p Γ) unsplitUsages₂-eq : ∀ {m n p} {γ : Context m} {δ : Context n} {θ : Context p} {p : γ ++ δ ≅ θ} {Γ : Usages γ} → let (_ , (_ , M₂) , _ , eq₂) = unsplitContext p in ∀ {Δ Θ} → [ p ] Γ ++ Δ ≅ Θ → Usages[ _≡_ , UsageEq ] eq₂ Θ (Δ U.⋈ unsplitUsages₂ p Γ) unsplitUsages₂-eq [] = [] unsplitUsages₂-eq (S ∷ˡ eq) = Eq.refl ∷ (unsplitUsages₂-eq eq) unsplitUsages₂-eq (S ∷ʳ eq) = Eq.refl ∷ (unsplitUsages₂-eq eq) mixFin : Mix TFin mixFin {Γ₁ = Γ₁} {Γ₂} {p = p} {q} eqΓ eqΔ eqΓ′ eqΔ′ K = case splitFin p eqΓ eqΔ K of λ { (inj₁ (k , K , Γ₂≡Δ₂)) → let (_ , _ , eq₁ , _) = unsplitContext q inc = unsplitUsages₁ q Γ₂ EQΓ′ = unsplitUsages₁-eq eqΓ′ EQΔ′ = unsplitUsages₁-eq eqΔ′ K′ = U.weakFin inc K EQΔ′ = UP.irrelevance _ (subst _ (Eq.sym Γ₂≡Δ₂) (UP.sym EQΔ′)) in , extensionalFin eq₁ (CP.sym eq₁) EQΓ′ EQΔ′ K′ ; (inj₂ (k , K , Γ₁≡Δ₁)) → let (_ , _ , _ , eq₂) = unsplitContext q inc = unsplitUsages₂ q Γ₁ EQΓ′ = unsplitUsages₂-eq eqΓ′ EQΔ′ = unsplitUsages₂-eq eqΔ′ K′ = U.weakFin inc K EQΔ′ = UP.irrelevance _ (subst _ (Eq.sym Γ₁≡Δ₁) (UP.sym EQΔ′)) in , extensionalFin eq₂ (CP.sym eq₂) EQΓ′ EQΔ′ K′ }