module plfa.part2.ConfluenceZ4 where
open import Relation.Binary.PropositionalEquality using (_≡_; refl; sym; cong; cong₂)
open import Function using (_∘_)
open import Data.Product using (_×_; Σ; Σ-syntax; ∃; ∃-syntax; proj₁; proj₂)
renaming (_,_ to ⟨_,_⟩)
open import plfa.part2.Substitution using (Rename; Subst; rename-subst-commute; subst-commute; ren; cong-sub; extensionality)
open import plfa.part2.Untyped
using (_—→_; β; ξ₁; ξ₂; ζ; _—↠_; begin_; _—→⟨_⟩_; _—↠⟨_⟩_; _∎;
abs-cong; appL-cong; appR-cong; —↠-trans;
_⊢_; _∋_; `_; #_; _,_; ★; ƛ_; _·_; _[_];
rename; ext; exts; Z; S_; subst; subst-zero)
app-cong : ∀{Γ} {K L M N : Γ ⊢ ★} → K —↠ L → M —↠ N → K · M —↠ L · N
app-cong Ψ Χ = —↠-trans (appL-cong Ψ) (appR-cong Χ)
stp-rename : ∀{Γ Δ A} {ρ : Rename Γ Δ} (M : Γ ⊢ A) {N : Γ ⊢ A}
→ M —→ N
→ rename ρ M —→ rename ρ N
stp-rename (ƛ M) (ζ φ) = ζ (stp-rename M φ)
stp-rename (M · _) (ξ₁ φ) = ξ₁ (stp-rename M φ)
stp-rename (_ · M) (ξ₂ φ) = ξ₂ (stp-rename M φ)
stp-rename {ρ = ρ} ((ƛ L) · M) β with β {_} {rename (ext ρ) L} {rename ρ M}
... | G rewrite rename-subst-commute {_}{_}{L}{M}{ρ} = G
stp-subst : ∀{Γ Δ A} {σ : Subst Γ Δ} {M M′ : Γ ⊢ A}
→ M —→ M′
→ subst σ M —→ subst σ M′
stp-subst (ξ₁ φ) = ξ₁ (stp-subst φ)
stp-subst (ξ₂ φ) = ξ₂ (stp-subst φ)
stp-subst {σ = σ} (β {_} {L} {M}) with β {_} {subst (exts σ) L} {subst σ M}
... | G rewrite subst-commute {_}{_}{L}{M}{σ} = G
stp-subst {σ = σ} (ζ φ) = ζ (stp-subst {σ = exts σ} φ)
_—↠s_ : ∀{Γ Δ} → Subst Γ Δ → Subst Γ Δ → Set
_—↠s_ {Γ}{Δ} σ τ = ∀{A} → (x : Γ ∋ A) → σ x —↠ τ x
trm-subst : ∀{Γ Δ A} {σ τ : Subst Γ Δ}
→ σ —↠s τ
→ (M : Γ ⊢ A)
→ subst σ M —↠ subst τ M
trm-subst R (` x) = R x
trm-subst {σ = σ} {τ = τ} R (ƛ M) = abs-cong (trm-subst exts-rews M) where
rew-rename : ∀{Γ Δ A} {ρ : Rename Γ Δ} {M N : Γ ⊢ A}
→ M —↠ N
→ rename ρ M —↠ rename ρ N
rew-rename {ρ = ρ} (M ∎) = (rename ρ M) ∎
rew-rename {ρ = ρ} (M —→⟨ φ ⟩ Ψ) = rename ρ M —→⟨ stp-rename _ φ ⟩ rew-rename Ψ
exts-rews : ∀{B} → exts σ {B = B} —↠s exts τ
exts-rews Z = (` Z) ∎
exts-rews (S x) = rew-rename (R x)
trm-subst R (L · M) = app-cong (trm-subst R L) (trm-subst R M)
rew-rew : ∀{Γ} {M N : Γ , ★ ⊢ ★ } {K L : Γ ⊢ ★ }
→ M —↠ N
→ K —↠ L
→ M [ K ] —↠ N [ L ]
rew-rew {Γ} {K = K} {L} Ψ Χ = rews-subst Ψ where
rews-zero : subst-zero K —↠s subst-zero L
rews-zero Z = Χ
rews-zero (S x) = (` x) ∎
rews-subst : ∀{A} {M N : Γ , ★ ⊢ A} → M —↠ N
→ subst (subst-zero K) M —↠ subst (subst-zero L) N
rews-subst (M ∎) = trm-subst rews-zero M
rews-subst (_ —→⟨ φ ⟩ Ψ) = _ —→⟨ stp-subst φ ⟩ (rews-subst Ψ)
_• : ∀ {Γ A} → Γ ⊢ A → Γ ⊢ A
(` x)• = ` x
(ƛ M)• = ƛ (M •)
((ƛ M) · N)• = M • [ N • ]
(M · N)• = (M •) ·(N •)
extensive : ∀ {Γ A} → (M : Γ ⊢ A) → M —↠ M •
extensive (` _) = _ ∎
extensive (ƛ M) = abs-cong (extensive M)
extensive ((ƛ M) · N) = _ —→⟨ β ⟩ rew-rew (extensive M) (extensive N)
extensive (` _ · N) = appR-cong (extensive N)
extensive (L · M · N) = app-cong (extensive (L · M)) (extensive N)
upperbound : ∀ {Γ} → {M N : Γ ⊢ ★}
→ M —→ N
→ N —↠ M •
upperbound {_} {ƛ _} (ζ φ) = abs-cong (upperbound φ)
upperbound {_} {(` _) · _} {_} (ξ₂ φ) = appR-cong (upperbound φ)
upperbound {_} {(ƛ _) · M} {((ƛ _) · M)} (ξ₁ (ζ φ)) = _ —→⟨ β ⟩ rew-rew (upperbound φ) (extensive M)
upperbound {_} {(ƛ L) · _} {.((ƛ L) · _)} (ξ₂ φ) = _ —→⟨ β ⟩ rew-rew (extensive L) (upperbound φ)
upperbound {_} {(ƛ L) · M} {.(subst (subst-zero M) L)} β = rew-rew (extensive L) (extensive M)
upperbound {_} {_ · _ · M} {.(_ · M)} (ξ₁ φ) = app-cong (upperbound φ) (extensive M)
upperbound {_} {K · L · _} {.(_ · _ · _)} (ξ₂ φ) = app-cong (extensive (K · L)) (upperbound φ)
rename-bullet : ∀{Γ Δ} (ρ : Rename Γ Δ) {A} (M : Γ ⊢ A) → rename ρ (M •) ≡ rename ρ M •
rename-bullet _ (` x) = refl
rename-bullet ρ (ƛ M) = cong ƛ_ (rename-bullet (ext ρ) M)
rename-bullet ρ ((` x) · M) rewrite rename-bullet ρ M = refl
rename-bullet ρ ((ƛ L) · M) rewrite sym (rename-subst-commute {_} {_} {L •} {M •} {ρ})
rewrite rename-bullet ρ M rewrite rename-bullet (ext ρ) L = refl
rename-bullet ρ (K · L · M) = cong₂ _·_ (rename-bullet ρ (K · L)) (rename-bullet ρ M)
exts-bullet : ∀{Γ Δ} {σ τ : Subst Γ Δ}
→ ((x : Γ ∋ ★) → τ x ≡ σ x •)
→ (x : Γ , ★ ∋ ★) → exts τ x ≡ exts σ x •
exts-bullet eq Z = refl
exts-bullet {σ = σ} eq (S x) rewrite (eq x) = rename-bullet S_ (σ x)
rhss : ∀{Γ Δ} (M : Γ ⊢ ★) {σ τ : Subst Γ Δ} → ((x : Γ ∋ ★) → τ x ≡ σ x •)
→ subst τ (M •) —↠ (subst σ M)•
rhss (` x) eq rewrite (eq x) = _ ∎
rhss (ƛ M) eq = abs-cong (rhss M (exts-bullet eq))
rhss ((` x) · M) {σ} eq rewrite (eq x) = —↠-trans
(appR-cong (rhss M eq)) (app-bullet (σ x) (subst σ M)) where
app-bullet : ∀{Γ} (L M : Γ ⊢ ★) → L • · M • —↠ (L · M)•
app-bullet (` _) _ = _ ∎
app-bullet (ƛ _) _ = (_ —→⟨ β ⟩ _ ∎)
app-bullet (_ · _) _ = _ ∎
rhss ((ƛ L) · M) {τ = τ} eq rewrite (sym (subst-commute {N = L •} {M •} {τ})) =
rew-rew (rhss L (exts-bullet eq)) (rhss M eq)
rhss (K · L · M) eq = app-cong (rhss (K · L) eq) (rhss M eq)
monotonic : ∀{Γ} → {M N : Γ ⊢ ★}
→ M —→ N
→ M • —↠ N •
monotonic (ζ φ) = abs-cong (monotonic φ)
monotonic {_} {(` _) · _} {(` _) · _} (ξ₂ φ) = appR-cong (monotonic φ)
monotonic {Γ} {(ƛ M) · N} {.(subst (subst-zero N) M)} β = rhss M bullet-zero where
bullet-zero : (x : Γ , ★ ∋ ★) → subst-zero (N •) x ≡ subst-zero N x •
bullet-zero Z = refl
bullet-zero (S x) = refl
monotonic {_} {(ƛ _) · _} {(ƛ _) · _} (ξ₁ (ζ φ)) = rew-rew (monotonic φ) (_ ∎)
monotonic {_} {(ƛ M) · _} {.((ƛ M) · _)} (ξ₂ φ) = rew-rew (M • ∎) (monotonic φ)
monotonic {_} {_ · _ · _} {(ƛ _) · _} (ξ₁ φ) = —↠-trans (appL-cong (monotonic φ)) (_ —→⟨ β ⟩ _ ∎)
monotonic {_} {_ · _ · _} {(` _) · _} (ξ₁ φ) = appL-cong (monotonic φ)
monotonic {_} {_ · _ · _} {_ · _ · _} (ξ₁ φ) = appL-cong (monotonic φ)
monotonic {_} {_ · _ · _} {_ · _ · _} (ξ₂ φ) = appR-cong (monotonic φ)
rew-monotonic : ∀{Γ} → {M N : Γ ⊢ ★}
→ M —↠ N
→ M • —↠ N •
rew-monotonic (_ ∎) = _ ∎
rew-monotonic (_ —→⟨ φ ⟩ Ψ) = —↠-trans (monotonic φ) (rew-monotonic Ψ)
strip : ∀{Γ} {L M N : Γ ⊢ ★}
→ L —→ M
→ L —↠ N
→ Σ[ K ∈ Γ ⊢ ★ ] (M —↠ K) × (N —↠ K)
strip {L = L} {N = N} φ Ψ = ⟨ N • ,
⟨ —↠-trans (upperbound φ) (rew-monotonic Ψ) , extensive N ⟩ ⟩
confluence : ∀{Γ} {L M N : Γ ⊢ ★}
→ L —↠ M
→ L —↠ N
→ Σ[ K ∈ Γ ⊢ ★ ] (M —↠ K) × (N —↠ K)
confluence (_ ∎) Χ = ⟨ _ , ⟨ Χ , _ ∎ ⟩ ⟩
confluence (_ —→⟨ φ ⟩ Ψ) Χ =
⟨ _ , ⟨ proj₁ d2 , —↠-trans (proj₂ d1) (proj₂ d2) ⟩ ⟩ where
d1 = proj₂ (strip φ Χ)
d2 = proj₂ (confluence Ψ (proj₁ d1))