module Record.Algo.Uniqueness where
open import Record.Prelude hiding (_≤?_) renaming (_≤_ to _≤n_)
open import Record.Common
open import Record.Properties
open import Record.Algo
open import Record.Algo.Properties
open import Record.Algo.WellFormed
⊢unique : ∀ {Γ Σ e A B}
→ WFG Γ → WFΣ Σ → WFE e
→ Γ ⊢ Σ ⇒ e ⇒ A
→ Γ ⊢ Σ ⇒ e ⇒ B
→ A ≡ B
#-false' : ∀ {Γ e}
→ WFG Γ
→ WFE e
→ Value e
→ Γ ⊢ τ Int ⇒ e ⇒ Int
→ Γ ⊢ τ Float ⇒ e ⇒ Float
→ ⊥
#-false' wfg wfe (V-n {+s}) (⊢sub p-e ⊢c (≤and-l () x) Σ≢□) (⊢sub p-e₁ ⊢c A≤Σ₁ Σ≢□₁)
#-false' wfg wfe (V-n {+s}) (⊢sub p-e ⊢c (≤and-r () x) Σ≢□) (⊢sub p-e₁ ⊢c A≤Σ₁ Σ≢□₁)
#-false' wfg wfe (V-n {c}) (⊢sub p-e ⊢c A≤Σ Σ≢□) (⊢sub p-e₁ (⊢sub p-e₂ ⊢2 A≤Σ₂ Σ≢□₂) A≤Σ₁ Σ≢□₁) = ⊥-elim (Σ≢□₂ refl)
#-false' wfg wfe V-n (⊢sub p-e (⊢sub p-e₁ ⊢1 A≤Σ₁ Σ≢□₁) A≤Σ Σ≢□) ⊢2 = ⊥-elim (Σ≢□₁ refl)
#-false' wfg wfe V-ƛ (⊢sub p-e (⊢sub p-e₁ ⊢1 A≤Σ₁ Σ≢□₁) A≤Σ Σ≢□) ⊢2 = ⊥-elim (Σ≢□₁ refl)
#-eq : ∀ {Γ A B C D Σ}
→ Σ ≢ □
→ WFG Γ
→ WFΣ Σ
→ WF A
→ WF B
→ A # B
→ Γ ⊢ A ≤ Σ ⇝ C
→ Γ ⊢ B ≤ Σ ⇝ D
→ C ≡ D
#-eq Σ≢□ wfg wfh wfA wfB (#-and-l A#B A#B₁) ≤top s2 = sym (≤id-0 s2)
#-eq Σ≢□ wfg wfh wfA wfB (#-and-l A#B A#B₁) ≤□ s2 = ⊥-elim (Σ≢□ refl)
#-eq Σ≢□ wfg wfh (wf-and wfA wfA₁ A#B₂) wfB (#-and-l A#B A#B₁) (≤and-l s1 x) s2 = #-eq Σ≢□ wfg wfh wfA wfB A#B s1 s2
#-eq Σ≢□ wfg wfh (wf-and wfA wfA₁ A#B₂) wfB (#-and-l A#B A#B₁) (≤and-r s1 x) s2 = #-eq Σ≢□ wfg wfh wfA₁ wfB A#B₁ s1 s2
#-eq Σ≢□ wfg wfh wfA wfB (#-and-l A#B A#B₁) (≤and s1 s3) s2 with ≤id-0 s1 | ≤id-0 s3 | ≤id-0 s2
... | refl | refl | refl = refl
#-eq Σ≢□ wfg wfh wfA wfB (#-and-r A#B A#B₁) s1 ≤top = ≤id-0 s1
#-eq Σ≢□ wfg wfh wfA wfB (#-and-r A#B A#B₁) s1 ≤□ = ⊥-elim (Σ≢□ refl)
#-eq Σ≢□ wfg wfh wfA (wf-and wfB wfB₁ A#B₂) (#-and-r A#B A#B₁) s1 (≤and-l s2 x) = #-eq Σ≢□ wfg wfh wfA wfB A#B s1 s2
#-eq Σ≢□ wfg wfh wfA (wf-and wfB wfB₁ A#B₂) (#-and-r A#B A#B₁) s1 (≤and-r s2 x) = #-eq Σ≢□ wfg wfh wfA wfB₁ A#B₁ s1 s2
#-eq Σ≢□ wfg wfh wfA wfB (#-and-r A#B A#B₁) s1 (≤and s2 s3) with ≤id-0 s1 | ≤id-0 s2 | ≤id-0 s3
... | refl | refl | refl = refl
#-eq Σ≢□ wfg wfh wfA wfB #-base-1 ≤top s2 = sym (≤id-0 s2)
#-eq Σ≢□ wfg wfh wfA wfB #-base-1 ≤□ s2 = ⊥-elim (Σ≢□ refl)
#-eq Σ≢□ wfg wfh wfA wfB #-base-1 (≤arr s1 s3) s2 = sym (≤id-0 s2)
#-eq Σ≢□ wfg (wfh-e wfh wfe ve) wfA wfB #-base-1 (≤hint x s1) (≤hint x₁ s2) with ⊢id-0 x₁ | ⊢id-0 x
... | refl | refl = ⊥-elim (#-false' wfg wfe ve x x₁)
#-eq Σ≢□ wfg wfh wfA wfB #-base-1 (≤and s1 s3) s2 with ≤id-0 s1 | ≤id-0 s2 | ≤id-0 s3
... | refl | refl | refl = refl
#-eq Σ≢□ wfg wfh wfA wfB #-base-2 ≤top s2 = sym (≤id-0 s2)
#-eq Σ≢□ wfg wfh wfA wfB #-base-2 ≤□ s2 = ⊥-elim (Σ≢□ refl)
#-eq Σ≢□ wfg wfh wfA wfB #-base-2 (≤arr s1 s3) s2 = sym (≤id-0 s2)
#-eq Σ≢□ wfg (wfh-e wfh wfe ve) wfA wfB #-base-2 (≤hint x s1) (≤hint x₁ s2) with ⊢id-0 x₁ | ⊢id-0 x
... | refl | refl = ⊥-elim (#-false' wfg wfe ve x₁ x)
#-eq Σ≢□ wfg wfh wfA wfB #-base-2 (≤and s1 s3) s2 with ≤id-0 s1 | ≤id-0 s2 | ≤id-0 s3
... | refl | refl | refl = refl
#-eq Σ≢□ wfg wfh wfA wfB (#-rcd x) ≤top s2 = sym (≤id-0 s2)
#-eq Σ≢□ wfg wfh wfA wfB (#-rcd x) ≤□ s2 = ⊥-elim (Σ≢□ refl)
#-eq Σ≢□ wfg wfh wfA wfB (#-rcd x) (≤rcd s1) s2 with ≤id-0 s1 | ≤id-0 s2
... | refl | refl = refl
#-eq Σ≢□ wfg (wfh-l wfh) wfA wfB (#-rcd x) (≤hint-l s1) (≤hint-l s2) = ⊥-elim (x refl)
#-eq Σ≢□ wfg wfh wfA wfB (#-rcd x) (≤and s1 s3) s2 with ≤id-0 s1 | ≤id-0 s2 | ≤id-0 s3
... | refl | refl | refl = refl
≤unique : ∀ {Γ A Σ B C}
→ WFG Γ → WF A → WFΣ Σ
→ Γ ⊢ A ≤ Σ ⇝ B
→ Γ ⊢ A ≤ Σ ⇝ C
→ B ≡ C
⊢r-unique : ∀ {Γ Σ rs A B}
→ WFG Γ → WFΣ Σ → WFR rs
→ Γ ⊢r Σ ⇒ rs ⇒ A
→ Γ ⊢r Σ ⇒ rs ⇒ B
→ A ≡ B
⊢r-unique wfg wfh wfr ⊢nil ⊢nil = refl
⊢r-unique wfg wfh-□ (wfr-cons x₂ wfr wfl) (⊢one x) (⊢one x₁) with ⊢unique wfg wfh-□ x₂ x x₁
... | refl = refl
⊢r-unique wfg wfh wfr (⊢one x) (⊢cons x₁ ⊢2 x₂) = ⊥-elim (x₂ refl)
⊢r-unique wfg wfh wfr (⊢cons x ⊢1 x₁) (⊢one x₂) = ⊥-elim (x₁ refl)
⊢r-unique wfg wfh-□ (wfr-cons x₄ wfr wfl) (⊢cons x ⊢1 x₁) (⊢cons x₂ ⊢2 x₃) with ⊢unique wfg wfh-□ x₄ x x₂ | ⊢r-unique wfg wfh-□ wfr ⊢1 ⊢2
... | refl | refl = refl
⊢unique wfg wfh wfe ⊢c ⊢c = refl
⊢unique wfg wfh wfe ⊢c (⊢sub p-e ⊢2 A≤Σ Σ≢□) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh wfe (⊢var x∈Γ) (⊢var x∈Γ₁) = x∈Γ-unique x∈Γ x∈Γ₁
⊢unique wfg wfh wfe (⊢var x∈Γ) (⊢sub p-e ⊢2 A≤Σ Σ≢□) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh wfe (⊢ann ⊢1) (⊢ann ⊢2) = refl
⊢unique wfg wfh wfe (⊢ann ⊢1) (⊢sub p-e ⊢2 A≤Σ Σ≢□) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh (wfe-app wfe wfe₁ ve) (⊢app ⊢1) (⊢app ⊢2) with ⊢unique wfg (wfh-e wfh wfe₁ ve) wfe ⊢1 ⊢2
... | refl = refl
⊢unique wfg (wfh-τ (wf-arr x x₁)) (wfe-lam wfe) (⊢lam₁ ⊢1) (⊢lam₁ ⊢2) with ⊢unique (wfg-, wfg x) (wfh-τ x₁) wfe ⊢1 ⊢2
... | refl = refl
⊢unique wfg (wfh-e wfh x ve) (wfe-lam wfe) (⊢lam₂ ⊢1 ⊢3) (⊢lam₂ ⊢2 ⊢4) with ⊢unique wfg wfh-□ x ⊢1 ⊢2
... | refl with ⊢unique (wfg-, wfg (⊢wf wfg wfh-□ x ⊢1)) (wf-⇧ wfh) wfe ⊢3 ⊢4
... | refl = refl
⊢unique wfg wfh wfe (⊢sub p-e ⊢1 A≤Σ Σ≢□) ⊢c = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh wfe (⊢sub p-e ⊢1 A≤Σ Σ≢□) (⊢var x∈Γ) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh wfe (⊢sub p-e ⊢1 A≤Σ Σ≢□) (⊢ann ⊢2) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh wfe (⊢sub p-e ⊢1 A≤Σ Σ≢□) (⊢sub p-e₁ ⊢2 A≤Σ₁ Σ≢□₁) with ⊢unique wfg wfh-□ wfe ⊢1 ⊢2
... | refl = ≤unique wfg (⊢wf wfg wfh-□ wfe ⊢1) wfh A≤Σ A≤Σ₁
⊢unique wfg wfh wfe (⊢sub p-e ⊢1 A≤Σ Σ≢□) (⊢rcd x) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh wfe (⊢rcd x) (⊢sub p-e ⊢2 A≤Σ Σ≢□) = ⊥-elim (Σ≢□ refl)
⊢unique wfg wfh (wfe-rcd x₂) (⊢rcd x) (⊢rcd x₁) = ⊢r-unique wfg wfh x₂ x x₁
⊢unique wfg wfh (wfe-prj wfe) (⊢prj ⊢1) (⊢prj ⊢2) with ⊢unique wfg (wfh-l wfh) wfe ⊢1 ⊢2
... | refl = refl
≤unique wfg wf wfh ≤int ≤int = refl
≤unique wfg wf wfh ≤float ≤float = refl
≤unique wfg wf wfh ≤top ≤top = refl
≤unique wfg (wf-and wf wf₁ A#B) wfh ≤top (≤and-l s2 x) = ≤unique wfg wf wfh ≤top s2
≤unique wfg (wf-and wf wf₁ A#B) wfh ≤top (≤and-r s2 x) = ≤unique wfg wf₁ wfh ≤top s2
≤unique wfg wf wfh ≤□ ≤□ = refl
≤unique wfg (wf-and wf wf₁ A#B) wfh ≤□ (≤and-l s2 x) = ⊥-elim (x refl)
≤unique wfg (wf-and wf wf₁ A#B) wfh ≤□ (≤and-r s2 x) = ⊥-elim (x refl)
≤unique wfg wf wfh (≤arr s1 s3) (≤arr s2 s4) = refl
≤unique wfg (wf-rcd wf) (wfh-τ (wf-rcd x)) (≤rcd s1) (≤rcd s2) rewrite ≤unique wfg wf (wfh-τ x) s1 s2 = refl
≤unique wfg (wf-arr wf wf₁) (wfh-e wfh x₂ ve) (≤hint x s1) (≤hint x₁ s2) rewrite ≤unique wfg wf₁ wfh s1 s2 = refl
≤unique wfg wf wfh (≤and-l s1 x) ≤top = ≤id-0 s1
≤unique wfg wf wfh (≤and-l s1 x) ≤□ = ⊥-elim (x refl)
≤unique wfg (wf-and wf wf₁ A#B) wfh (≤and-l s1 x) (≤and-l s2 x₁) = ≤unique wfg wf wfh s1 s2
≤unique wfg (wf-and wf wf₁ A#B) wfh (≤and-l s1 x) (≤and-r s2 x₁) = #-eq x wfg wfh wf wf₁ A#B s1 s2
≤unique wfg (wf-and wf wf₁ A#B) (wfh-τ (wf-and x₁ x₂ A#B₁)) (≤and-l s1 x) (≤and s2 s3)
rewrite ≤id-0 s2 | ≤id-0 s3 = ≤id-0 s1
≤unique wfg wf wfh (≤and-r s1 x) ≤top = ≤id-0 s1
≤unique wfg wf wfh (≤and-r s1 x) ≤□ = ⊥-elim (x refl)
≤unique wfg (wf-and wf wf₁ A#B) wfh (≤and-r s1 x) (≤and-l s2 x₁) = #-eq x wfg wfh wf₁ wf (#-comm A#B) s1 s2
≤unique wfg (wf-and wf wf₁ A#B) wfh (≤and-r s1 x) (≤and-r s2 x₁) = ≤unique wfg wf₁ wfh s1 s2
≤unique wfg (wf-and wf wf₁ A#B) (wfh-τ (wf-and x₁ x₂ A#B₁)) (≤and-r s1 x) (≤and s2 s3)
rewrite ≤id-0 s2 | ≤id-0 s3 = ≤id-0 s1
≤unique wfg (wf-and wf wf₁ A#B) (wfh-τ (wf-and x₁ x₂ A#B₁)) (≤and s1 s3) (≤and-l s2 x)
rewrite ≤id-0 s1 | ≤id-0 s3 = sym (≤id-0 s2)
≤unique wfg (wf-and wf wf₁ A#B) (wfh-τ (wf-and x₁ x₂ A#B₁)) (≤and s1 s3) (≤and-r s2 x)
rewrite ≤id-0 s1 | ≤id-0 s3 = sym (≤id-0 s2)
≤unique wfg wf wfh (≤and s1 s3) (≤and s2 s4)
rewrite ≤id-0 s1 | ≤id-0 s2 | ≤id-0 s3 | ≤id-0 s4 = refl
≤unique wfg (wf-rcd wf) (wfh-l wfh) (≤hint-l s1) (≤hint-l s2) with ≤unique wfg wf wfh s1 s2
... | refl = refl
⊢unique-0 : ∀ {Γ e A B}
→ WFG Γ → WFE e
→ Γ ⊢ □ ⇒ e ⇒ A
→ Γ ⊢ □ ⇒ e ⇒ B
→ A ≡ B
⊢unique-0 wfg wfe ⊢1 ⊢2 = ⊢unique wfg wfh-□ wfe ⊢1 ⊢2
⊢r-unique-0 : ∀ {Γ rs A B}
→ WFG Γ → WFR rs
→ Γ ⊢r □ ⇒ rs ⇒ A
→ Γ ⊢r □ ⇒ rs ⇒ B
→ A ≡ B
⊢r-unique-0 wfg wfr ⊢1 ⊢2 = ⊢r-unique wfg wfh-□ wfr ⊢1 ⊢2