\begin{code}
module Alpha where
open import Atom
open import Term
open import Equivariant
open import Permutation
open import ListProperties
open import Chi
open import TermAcc
open import Level
open import Relation.Nullary
open import Relation.Binary
open import Data.Empty
open import Data.Product renaming (_×_ to _∧_)
open import Data.Sum
open import Data.List
open import Data.List.Any as Any hiding (map)
open import Data.List.Any.Properties
open import Data.List.Any.Membership
open Any.Membership-≡
open import Relation.Binary.PropositionalEquality as PropEq hiding ([_])
infix 3 _∼α_ _≈α_
\end{code}
\begin{code}
data _∼α_ : Λ → Λ → Set where
∼αv : {a : Atom} → v a ∼α v a
∼α· : {M M' N N' : Λ} → M ∼α M' → N ∼α N'
→ M · N ∼α M' · N'
∼αƛ : {M N : Λ}{a b : Atom}(xs : List Atom)
→ ((c : Atom) → c ∉ xs → ( a ∙ c ) M ∼α ( b ∙ c ) N)
→ ƛ a M ∼α ƛ b N
\end{code}
\begin{code}
lemma∼αEquiv : EquivariantRel _∼α_
lemma∼αEquiv .{v a} .{v a} π (∼αv {a})
rewrite lemmaπv {a} {π} = ∼αv
lemma∼αEquiv .{M · N} .{M' · N'} π (∼α· {M} {M'} {N} {N'} M∼αM' N∼αN')
rewrite lemmaπ· {M} {N} {π} | lemmaπ· {M'} {N'} {π}
= ∼α· (lemma∼αEquiv π M∼αM') (lemma∼αEquiv π N∼αN')
lemma∼αEquiv .{ƛ a M} .{ƛ b N} π (∼αƛ {M} {N} {a} {b} xs p)
rewrite lemmaπƛ {a} {M} {π} | lemmaπƛ {b} {N} {π}
= ∼αƛ {π ∙ M} {π ∙ N} {π ∙ₐ a} {π ∙ₐ b} (xs ++ atoms π)
(λ c c∉xs++π → lemma-aux c π c∉xs++π)
where
lemma-aux : (c : Atom)(π : Π) → c ∉ xs ++ atoms π →
( π ∙ₐ a ∙ c ) (π ∙ M) ∼α ( π ∙ₐ b ∙ c ) (π ∙ N)
lemma-aux c π c∉xs++π
rewrite
cong (λ w → ( π ∙ₐ a ∙ w ) (π ∙ M))
(sym (lemmaπ∙ₐ≡ {c} {π} (c∉xs++ys→c∉ys {c} {xs} c∉xs++π)))
| cong (λ w → ( π ∙ₐ b ∙ w ) (π ∙ N))
(sym (lemmaπ∙ₐ≡ {c} {π} (c∉xs++ys→c∉ys {c} {xs} c∉xs++π)))
| sym (lemmaπ∙distributive {a} {c} {M} {π})
| sym (lemmaπ∙distributive {b} {c} {N} {π})
= lemma∼αEquiv π (p c (c∉xs++ys→c∉xs c∉xs++π))
lemma∼αƛ : {a : Atom}{M N : Λ} → M ∼α N → ƛ a M ∼α ƛ a N
lemma∼αƛ {a} {M} {N} M∼αN = ∼αƛ [] (λ c c∉[] → lemma∼αEquiv [(a , c)] M∼αN)
ρ : Reflexive _∼α_
ρ {v a} = ∼αv
ρ {M · N} = ∼α· ρ ρ
ρ {ƛ a M} = ∼αƛ [] (λ c c∉[] → lemma∼αEquiv {M} {M} [ (a , c) ] ρ)
σ : Symmetric _∼α_
σ ∼αv = ∼αv
σ (∼α· M∼αM' N∼αN') = ∼α· (σ M∼αM') (σ N∼αN')
σ (∼αƛ xs p) = ∼αƛ xs (λ c c∉xs → σ (p c c∉xs))
τ : Transitive _∼α_
τ ∼αv ∼αv = ∼αv
τ (∼α· M∼αM′ N∼αN′) (∼α· M′∼αM″ N′∼αN″) = ∼α· (τ M∼αM′ M′∼αM″) (τ N∼αN′ N′∼αN″)
τ (∼αƛ xs p) (∼αƛ xs′ p′)
= ∼αƛ (xs ++ xs′)
(λ c c∉xs++xs′ →
τ (p c (c∉xs++ys→c∉xs c∉xs++xs′))
(p′ c (c∉xs++ys→c∉ys {c} {xs} c∉xs++xs′)))
≈-preorder : Preorder _ _ _
≈-preorder =
record {
Carrier = Λ;
_≈_ = _≡_;
_∼_ = _∼α_;
isPreorder = record {
isEquivalence = Relation.Binary.Setoid.isEquivalence (setoid Λ) ;
reflexive = λ { {M} {.M} refl → ρ};
trans = τ } }
import Relation.Binary.PreorderReasoning as PreR
open PreR ≈-preorder
lemma∙cancel∼α : {a b c : Atom}{M : Λ} → b # M → c # M →
( c ∙ b ) ( a ∙ c ) M ∼α ( a ∙ b ) M
lemma∙cancel∼α {a} {b} {c} {M} b#M c#M with a ≟ₐ b
lemma∙cancel∼α {a} {.a} {c} {M} a#M c#M
| yes refl = begin
( c ∙ a ) ( a ∙ c ) M
≈⟨ lemma∙comm ⟩
( a ∙ c ) ( a ∙ c ) M
≈⟨ lemma(ab)(ab)M≡M ⟩
M
≈⟨ sym lemma(aa)M≡M ⟩
( a ∙ a ) M
∎
lemma∙cancel∼α {a} {b} {c} {M} b#M c#M
| no a≢b with a ≟ₐ c
lemma∙cancel∼α {a} {b} {.a} {M} b#M a#M
| no a≢b | yes refl = begin
( a ∙ b ) ( a ∙ a ) M
≈⟨ cong (λ x → ( a ∙ b ) x) lemma(aa)M≡M ⟩
( a ∙ b ) M
∎
lemma∙cancel∼α {a} {b} {c} {M} b#M c#M
| no a≢b | no a≢c with b ≟ₐ c
lemma∙cancel∼α {a} {b} {.b} {M} b#M c#M
| no a≢b | no a≢c | yes refl = begin
( b ∙ b ) ( a ∙ b ) M
≈⟨ lemma(aa)M≡M ⟩
( a ∙ b ) M
∎
lemma∙cancel∼α {a} {b} {c} {v d} (#v d≢b) (#v d≢c) | no a≢b | no a≢c | no b≢c
= begin
( c ∙ b ) ( a ∙ c ) (v d)
≈⟨ refl ⟩
v (( c ∙ b )ₐ ( a ∙ c )ₐ d)
≈⟨ cong v (lemma∙ₐcancel {a} {b} {c} {d} d≢b d≢c) ⟩
v (( a ∙ b )ₐ d)
≈⟨ refl ⟩
( a ∙ b ) (v d)
∎
lemma∙cancel∼α {a} {b} {c} {M · N} (#· b#M b#N) (#· c#M c#N) | no a≢b | no a≢c | no b≢c
= ∼α· (lemma∙cancel∼α b#M c#M) (lemma∙cancel∼α b#N c#N)
lemma∙cancel∼α {a} {b} {c} {ƛ d M} b#λdM c#λdM | no a≢b | no a≢c | no b≢c
with b ≟ₐ d
lemma∙cancel∼α {a} {b} {.b} {ƛ .b M} b#λdM #ƛ≡ | no a≢b | no _ | no b≢b
| yes refl = ⊥-elim (b≢b refl)
lemma∙cancel∼α {a} {b} {c} {ƛ .b M} b#λdM (#ƛ c#M) | no a≢b | no a≢c | no b≢c
| yes refl
rewrite lemma∙ₐ(ab)b≡a {a} {b} | lemma∙ₐc≢a∧c≢b (sym≢ a≢b) b≢c | lemma∙ₐ(ab)b≡a {c} {b}
= ∼αƛ (a ∷ b ∷ c ∷ ocurr M) (λ e e∉abc∷ocurrM → lemma(ce)(cb)(ac)M∼α(ae)(ab)M e e∉abc∷ocurrM)
where
lemma(ce)(cb)(ac)M∼α(ae)(ab)M : (e : Atom) → e ∉ a ∷ b ∷ c ∷ ocurr M → ( c ∙ e ) ( c ∙ b ) ( a ∙ c ) M ∼α ( a ∙ e ) ( a ∙ b ) M
lemma(ce)(cb)(ac)M∼α(ae)(ab)M e e∉abc∷ocurrM
= begin
( c ∙ e ) ( c ∙ b ) ( a ∙ c ) M
≈⟨ lemma∙distributive {c} {e} {c} {b} {( a ∙ c ) M} ⟩
( ( c ∙ e )ₐ c ∙ ( c ∙ e )ₐ b ) ( c ∙ e ) ( a ∙ c ) M
≈⟨ cong (λ x → ( x ∙ ( c ∙ e )ₐ b ) ( c ∙ e ) ( a ∙ c ) M) (lemma∙ₐ(ab)a≡b {c} {e}) ⟩
( e ∙ ( c ∙ e )ₐ b ) ( c ∙ e ) ( a ∙ c ) M
≈⟨ cong (λ x → ( e ∙ x ) ( c ∙ e ) ( a ∙ c ) M) (lemma∙ₐc≢a∧c≢b b≢c (sym≢ (d∉abc∷xs→d≢b e∉abc∷ocurrM))) ⟩
( e ∙ b ) ( c ∙ e ) ( a ∙ c ) M
∼⟨ lemma∼αEquiv [( e , b)] (lemma∙cancel∼α {a} {e} {c} (lemma∉→# {e} {M} (lemmaocurr (d∉abc∷xs→d∉xs e∉abc∷ocurrM))) c#M) ⟩
( e ∙ b ) ( a ∙ e ) M
≈⟨ sym (cong (λ x → ( e ∙ x ) ( a ∙ e ) M) (lemma∙ₐc≢a∧c≢b (sym≢ a≢b) (sym≢ (d∉abc∷xs→d≢b e∉abc∷ocurrM)))) ⟩
( e ∙ ( a ∙ e )ₐ b ) ( a ∙ e ) M
≈⟨ sym (cong (λ x → ( x ∙ ( a ∙ e )ₐ b ) ( a ∙ e ) M) (lemma∙ₐ(ab)a≡b {a} {e})) ⟩
( ( a ∙ e )ₐ a ∙ ( a ∙ e )ₐ b ) ( a ∙ e ) M
≈⟨ sym (lemma∙distributive {a} {e} {a} {b} {M}) ⟩
( a ∙ e ) ( a ∙ b ) M
∎
lemma∙cancel∼α {a} {b} {c} {ƛ d M} b#λdM c#λdM | no a≢b | no a≢c | no b≢c
| no b≢d with c ≟ₐ d
lemma∙cancel∼α {a} {b} {.b} {ƛ .b M} #ƛ≡ c#λcM | no a≢b | no a≢d | no _ | no b≢b
| yes refl = ⊥-elim (b≢b refl)
lemma∙cancel∼α {a} {b} {c} {ƛ .c M} (#ƛ b#M) c#λcM | no a≢b | no a≢c | no _ | no b≢c
| yes refl rewrite lemma∙ₐ(ab)b≡a {a} {c} | lemma∙ₐc≢a∧c≢b a≢c a≢b | lemma∙ₐc≢a∧c≢b (sym≢ a≢c) (sym≢ b≢c)
= ∼αƛ (a ∷ b ∷ c ∷ ocurr M) (λ e e∉abc∷ocurrM → lemma(ae)(cb)(ac)M∼α(ce)(ab)M e e∉abc∷ocurrM)
where
lemma(ae)(cb)(ac)M∼α(ce)(ab)M : (e : Atom) → e ∉ a ∷ b ∷ c ∷ ocurr M → ( a ∙ e ) ( c ∙ b ) ( a ∙ c ) M ∼α ( c ∙ e ) ( a ∙ b ) M
lemma(ae)(cb)(ac)M∼α(ce)(ab)M e e∉abc∷ocurrM
= begin
( a ∙ e ) ( c ∙ b ) ( a ∙ c ) M
≈⟨ cong (λ x → ( a ∙ e ) x) (lemma∙distributive {c} {b} {a} {c} {M}) ⟩
( a ∙ e ) ( ( c ∙ b )ₐ a ∙ ( c ∙ b )ₐ c ) ( c ∙ b ) M
≈⟨ cong (λ x → ( a ∙ e ) ( x ∙ ( c ∙ b )ₐ c ) ( c ∙ b ) M) (lemma∙ₐc≢a∧c≢b a≢c a≢b) ⟩
( a ∙ e ) ( a ∙ ( c ∙ b )ₐ c ) ( c ∙ b ) M
≈⟨ cong (λ x → ( a ∙ e ) ( a ∙ x ) ( c ∙ b ) M) (lemma∙ₐ(ab)a≡b {c} {b}) ⟩
( a ∙ e ) ( a ∙ b ) ( c ∙ b ) M
≈⟨ lemma∙distributive {a} {e} {a} {b} {( c ∙ b ) M} ⟩
( ( a ∙ e )ₐ a ∙ ( a ∙ e )ₐ b ) ( a ∙ e ) ( c ∙ b ) M
≈⟨ cong (λ x → ( x ∙ ( a ∙ e )ₐ b ) ( a ∙ e ) ( c ∙ b ) M) (lemma∙ₐ(ab)a≡b {a} {e}) ⟩
( e ∙ ( a ∙ e )ₐ b ) ( a ∙ e ) ( c ∙ b ) M
≈⟨ cong (λ x → ( e ∙ x ) ( a ∙ e ) ( c ∙ b ) M) (lemma∙ₐc≢a∧c≢b (sym≢ a≢b) (sym≢ (d∉abc∷xs→d≢b e∉abc∷ocurrM))) ⟩
( e ∙ b ) ( a ∙ e ) ( c ∙ b ) M
≈⟨ lemma∙distributive {e} {b} {a} {e} {( c ∙ b ) M} ⟩
( ( e ∙ b )ₐ a ∙ ( e ∙ b )ₐ e ) ( e ∙ b ) ( c ∙ b ) M
≈⟨ cong (λ x → ( x ∙ ( e ∙ b )ₐ e ) ( e ∙ b ) ( c ∙ b ) M) (lemma∙ₐc≢a∧c≢b (sym≢ (d∉abc∷xs→d≢a e∉abc∷ocurrM)) a≢b) ⟩
( a ∙ ( e ∙ b )ₐ e ) ( e ∙ b ) ( c ∙ b ) M
≈⟨ cong (λ x → ( a ∙ x ) ( e ∙ b ) ( c ∙ b ) M) (lemma∙ₐ(ab)a≡b {e} {b}) ⟩
( a ∙ b ) ( e ∙ b ) ( c ∙ b ) M
≈⟨ cong (λ x → ( a ∙ b ) x) (lemma∙comm {e} {b} {( c ∙ b ) M }) ⟩
( a ∙ b ) ( b ∙ e ) ( c ∙ b ) M
∼⟨ lemma∼αEquiv [(a , b)] (lemma∙cancel∼α {c} {e} {b} {M} (lemma∉→# {e} {M} (lemmaocurr (d∉abc∷xs→d∉xs e∉abc∷ocurrM))) b#M) ⟩
( a ∙ b ) ( c ∙ e ) M
≈⟨ sym (cong (λ x → ( a ∙ x ) ( c ∙ e ) M) (lemma∙ₐc≢a∧c≢b b≢c (sym≢ (d∉abc∷xs→d≢b e∉abc∷ocurrM)))) ⟩
( a ∙ ( c ∙ e )ₐ b ) ( c ∙ e ) M
≈⟨ sym (cong (λ x → ( x ∙ ( c ∙ e )ₐ b ) ( c ∙ e ) M) (lemma∙ₐc≢a∧c≢b a≢c (sym≢ (d∉abc∷xs→d≢a e∉abc∷ocurrM)))) ⟩
( ( c ∙ e )ₐ a ∙ ( c ∙ e )ₐ b ) ( c ∙ e ) M
≈⟨ sym (lemma∙distributive {c} {e} {a} {b} {M}) ⟩
( c ∙ e ) ( a ∙ b ) M
∎
lemma∙cancel∼α {a} {b} {c} {ƛ .b M} #ƛ≡ c#λdM | no a≢b | no a≢c | no b≢c | no b≢b
| no c≢b = ⊥-elim (b≢b refl)
lemma∙cancel∼α {a} {b} {c} {ƛ .c M} (#ƛ b#M) #ƛ≡ | no a≢b | no a≢c | no b≢c | no _
| no c≢c = ⊥-elim (c≢c refl)
lemma∙cancel∼α {a} {b} {c} {ƛ d M} (#ƛ b#M) (#ƛ c#M) | no a≢b | no a≢c | no b≢c | no b≢d
| no c≢d with a ≟ₐ d
lemma∙cancel∼α {a} {b} {c} {ƛ .a M} (#ƛ b#M) (#ƛ c#M) | no a≢b | no a≢c | no b≢c | no b≢a
| no c≢a | yes refl rewrite lemma∙ₐ(ab)a≡b {a} {c} | lemma∙ₐ(ab)a≡b {c} {b} | lemma∙ₐ(ab)a≡b {a} {b}
= lemma∼αƛ (lemma∙cancel∼α b#M c#M)
lemma∙cancel∼α {a} {b} {c} {ƛ d M} (#ƛ b#M) (#ƛ c#M) | no a≢b | no a≢c | no b≢c | no b≢d
| no c≢d | no a≢d rewrite lemma∙ₐc≢a∧c≢b (sym≢ a≢d) (sym≢ c≢d) | lemma∙ₐc≢a∧c≢b (sym≢ c≢d) (sym≢ b≢d) | lemma∙ₐc≢a∧c≢b (sym≢ a≢d) (sym≢ b≢d)
= lemma∼αƛ (lemma∙cancel∼α b#M c#M)
lemma∙cancel∼α' : {a b c : Atom}{M : Λ} → b # ƛ a M → c # M → ( c ∙ b ) ( a ∙ c ) M ∼α ( a ∙ b ) M
lemma∙cancel∼α' {a} {.a} {c} {M} #ƛ≡ c#M
= begin
( c ∙ a ) ( a ∙ c ) M
≈⟨ lemma∙comm {c} {a} {( a ∙ c ) M} ⟩
( a ∙ c ) ( a ∙ c ) M
≈⟨ lemma(ab)(ab)M≡M {a} {c} {M} ⟩
M
≈⟨ sym (lemma(aa)M≡M {a} {M}) ⟩
( a ∙ a ) M
∎
lemma∙cancel∼α' {a} {b} {c} {M} (#ƛ b#M) c#M
= lemma∙cancel∼α {a} {b} {c} {M} b#M c#M
lemma∙cancel∼α'' : {a b c : Atom}{M : Λ} → b # ƛ a M → c # ƛ a M → ( c ∙ b ) ( a ∙ c ) M ∼α ( a ∙ b ) M
lemma∙cancel∼α'' {a} {b} {.a} {M} b#ƛaM #ƛ≡ rewrite lemma(aa)M≡M {a} {M} = ρ
lemma∙cancel∼α'' b#ƛaM (#ƛ c#M) = lemma∙cancel∼α' b#ƛaM c#M
lemma∙cancel∼α‴ : {a b c : Atom}{M : Λ} → b # M → c # ƛ a M → ( c ∙ b ) ( a ∙ c ) M ∼α ( a ∙ b ) M
lemma∙cancel∼α‴ {a} {b} {.a} {M} b#M #ƛ≡ rewrite lemma(aa)M≡M {a} {M} = ρ
lemma∙cancel∼α‴ {a} {b} {c} {M} b#M (#ƛ c#N) = lemma∙cancel∼α b#M c#N
lemma∙ : {a b c : Atom}{M : Λ} → b # ƛ a M → c ∉ₜ M → ( c ∙ b ) ( a ∙ c ) M ∼α ( a ∙ b ) M
lemma∙ {a} {b} {c} {M} b#ƛaM c∉M
= lemma∙cancel∼α' {a} {b} {c} {M} b#ƛaM (lemma∉→# c∉M)
lemma∼α* : {a : Atom}{M N : Λ} → M ∼α N → a * M → a * N
lemma∼α* {a} ∼αv a*M = a*M
lemma∼α* {a} (∼α· M∼αM' N∼αN') (*·l a*M) = *·l (lemma∼α* M∼αM' a*M)
lemma∼α* {a} (∼α· M∼αM' N∼αN') (*·r a*N) = *·r (lemma∼α* N∼αN' a*N)
lemma∼α* {a} {ƛ b M} {ƛ c N} (∼αƛ xs f) (*ƛ a*M b≢a)
with
χ' (a ∷ b ∷ c ∷ [] ++ xs ++ ocurr N) |
c∉xs++ys→c∉xs {χ' (a ∷ b ∷ c ∷ [] ++ xs ++ ocurr N)} {xs} {ocurr N} (c∉xs++ys→c∉ys {χ' (a ∷ b ∷ c ∷ [] ++ xs ++ ocurr N)} {a ∷ b ∷ c ∷ []} {xs ++ ocurr N} (χ'∉ (a ∷ b ∷ c ∷ [] ++ xs ++ ocurr N))) |
(χ'∉ (a ∷ b ∷ c ∷ [] ++ xs ++ ocurr N))
... | d | d∉xs | d∉abcxsN
with lemma*swap← (lemma∼α* (f d d∉xs) (lemma*swap→ a≢d (sym≢ b≢a) a*M))
where
a≢d : a ≢ d
a≢d a≡d = d∉abcxsN (here (sym a≡d))
lemma∼α* {a} {ƛ b M} {ƛ c N} (∼αƛ xs f) (*ƛ a*M b≢a)
| d | d∉xs | d∉abcxsN | inj₁ (a≢c , _ , a*N) = *ƛ a*N (sym≢ a≢c)
lemma∼α* {a} {ƛ b M} {ƛ c N} (∼αƛ xs f) (*ƛ a*M b≢a)
| d | d∉xs | d∉abcxsN | inj₂ (inj₁ (a≡c , d*N)) = ⊥-elim ((¬d*N) d*N)
where
d∉N : d ∉ₜ N
d∉N = lemmaocurr (c∉xs++ys→c∉ys {d} {xs} {ocurr N} (c∉xs++ys→c∉ys {d} {a ∷ b ∷ c ∷ []} {xs ++ ocurr N} d∉abcxsN))
¬d*N : ¬ (d * N)
¬d*N d*N = (lemma∉→¬∈ d∉N) (lemma-free→∈ d*N)
lemma∼α* {a} {ƛ b M} {ƛ c N} (∼αƛ xs f) (*ƛ a*M b≢a)
| d | d∉xs | d∉abcxsN | inj₂ (inj₂ (a≡d , c*N)) = ⊥-elim (a≢d a≡d)
where
a≢d : a ≢ d
a≢d a≡d = d∉abcxsN (here (sym a≡d))
lemma∼α# : {a : Atom}{M N : Λ} → M ∼α N → a # M → a # N
lemma∼α# {a} {M} {N} M∼N a#M with a #? N
... | yes a#N = a#N
... | no ¬a#N = ⊥-elim (lemma-free→¬# (lemma∼α* (σ M∼N) (lemma¬#→free ¬a#N)) a#M)
χ∼α : (M N : Λ)(xs : List Atom) → M ∼α N → χ xs M ≡ χ xs N
χ∼α M N xs M∼αN = lemmaχaux⊆ (xs ++ fv M) (xs ++ fv N) lemma⊆ lemma⊇
where
lemma⊆ : (xs ++ fv M) ⊆ (xs ++ fv N)
lemma⊆ {a} a∈xs++fvM with c∈xs++ys→c∈xs∨c∈ys {a} {xs} {fv M} a∈xs++fvM
... | inj₁ a∈xs = c∈xs∨c∈ys→c∈xs++ys {a} {xs} {fv N} (inj₁ a∈xs)
... | inj₂ a∈fvM = c∈xs∨c∈ys→c∈xs++ys {a} {xs} {fv N} (inj₂ (lemmafvfree← a N (lemma∼α* M∼αN (lemmafvfree→ a M (a∈fvM)))))
lemma⊇ : (xs ++ fv N) ⊆ (xs ++ fv M)
lemma⊇ {a} a∈xs++fvN with c∈xs++ys→c∈xs∨c∈ys {a} {xs} {fv N} a∈xs++fvN
... | inj₁ a∈xs = c∈xs∨c∈ys→c∈xs++ys {a} {xs} {fv M} (inj₁ a∈xs)
... | inj₂ a∈fvN = c∈xs∨c∈ys→c∈xs++ys {a} {xs} {fv M} (inj₂ (lemmafvfree← a M (lemma∼α* (σ M∼αN) (lemmafvfree→ a N (a∈fvN)))))
data _≈α_ : Λ → Λ → Set where
≈αv : {a : Atom}
→ v a ≈α v a
≈α· : {M M' N N' : Λ} → M ≈α M' → N ≈α N'
→ M · N ≈α M' · N'
≈αƛ : {M N : Λ}{a b c : Atom}
→ c # ƛ a M → c # ƛ b N
→ ( a ∙ c ) M ≈α ( b ∙ c ) N
→ ƛ a M ≈α ƛ b N
lemma∼α∃#→∀ : {a b c : Atom}{M N : Λ} →
c # ƛ a M → c # ƛ b N → ( a ∙ c ) M ∼α ( b ∙ c ) N →
∃ (λ xs → ((d : Atom) → d ∉ xs → ( a ∙ d ) M ∼α ( b ∙ d ) N))
lemma∼α∃#→∀ {a} {b} {c} {M} {N} c#ƛaM c#ƛbN (ac)M∼α(bc)N
= ocurr M ++ ocurr N ,
(λ d d∉ocurrM++ocurrN →
(lemmaEqRel _∼α_ lemma∼αEquiv) [(d , c)]
( begin
( d ∙ c ) ( a ∙ d ) M
∼⟨ lemma∙ c#ƛaM (lemmaocurr (c∉xs++ys→c∉xs {d} {ocurr M} {ocurr N} d∉ocurrM++ocurrN)) ⟩
( a ∙ c ) M
∼⟨ (ac)M∼α(bc)N ⟩
( b ∙ c ) N
∼⟨ σ (lemma∙ c#ƛbN (lemmaocurr ((c∉xs++ys→c∉ys {d} {ocurr M} {ocurr N} d∉ocurrM++ocurrN)) )) ⟩
( d ∙ c ) ( b ∙ d ) N
∎ ))
lemma∼α∀→∃# : {a b : Atom}{M N : Λ}{xs : List Atom} →
((c : Atom) → c ∉ xs → ( a ∙ c ) M ∼α ( b ∙ c ) N) →
∃ (λ c → c # ƛ a M ∧ c # ƛ b N ∧ ( a ∙ c ) M ∼α ( b ∙ c ) N)
lemma∼α∀→∃# {a} {b} {M} {N} {xs} f
with χ' (xs ++ ocurr (ƛ a M) ++ ocurr (ƛ b N)) | χ'∉ (xs ++ ocurr (ƛ a M) ++ ocurr (ƛ b N))
... | c | c∉xs++ocurrƛaM++ocurrƛbN
= c ,
(lemma∉→#
(lemmaocurr
(c∉xs++ys→c∉xs {c} {ocurr (ƛ a M)} {ocurr (ƛ b N)}
(c∉xs++ys→c∉ys {c} {xs} {ocurr (ƛ a M) ++ ocurr (ƛ b N)} c∉xs++ocurrƛaM++ocurrƛbN)))) ,
(lemma∉→#
(lemmaocurr
(c∉xs++ys→c∉ys {c} {ocurr (ƛ a M)} {ocurr (ƛ b N)}
(c∉xs++ys→c∉ys {c} {xs} {ocurr (ƛ a M) ++ ocurr (ƛ b N)} c∉xs++ocurrƛaM++ocurrƛbN)))) ,
(f c (c∉xs++ys→c∉xs {c} {xs} {ocurr (ƛ a M) ++ ocurr (ƛ b N)} c∉xs++ocurrƛaM++ocurrƛbN))
lemma∼α→≈αAcc : {M N : Λ} → ΛAcc M → M ∼α N → M ≈α N
lemma∼α→≈αAcc _ ∼αv = ≈αv
lemma∼α→≈αAcc (acc· accM accN) (∼α· M∼αM' N∼αN') = ≈α· (lemma∼α→≈αAcc accM M∼αM') (lemma∼α→≈αAcc accN N∼αN')
lemma∼α→≈αAcc (accƛ facc) (∼αƛ _ f) with lemma∼α∀→∃# f
... | c , c#λaM , c#λbN , (ac)M∼α(bc)N = ≈αƛ {c = c} c#λaM c#λbN (lemma∼α→≈αAcc (facc c) (ac)M∼α(bc)N)
lemma∼α→≈α : {M N : Λ} → M ∼α N → M ≈α N
lemma∼α→≈α {M} M∼N = lemma∼α→≈αAcc {M} (accesibleTerms M) M∼N
lemma≈α→∼α : {M N : Λ} → M ≈α N → M ∼α N
lemma≈α→∼α ≈αv = ∼αv
lemma≈α→∼α (≈α· M≈αM' N≈αN') = ∼α· (lemma≈α→∼α M≈αM') (lemma≈α→∼α N≈αN')
lemma≈α→∼α (≈αƛ c#ƛaM c#ƛbN (ac)M∼α(bc)N)
with lemma∼α∃#→∀ c#ƛaM c#ƛbN (lemma≈α→∼α (ac)M∼α(bc)N)
... | xs , prf = ∼αƛ xs prf
lemma∼αλ : {a b : Atom}{M : Λ} → b # M → ƛ a M ∼α ƛ b (( a ∙ b ) M)
lemma∼αλ {a} {b} {M} b#M
= ∼αƛ (ocurr M) (λ c c∉ocurrM → σ (lemma∙cancel∼α (lemma∉→# (lemmaocurr c∉ocurrM)) b#M))
lemma∼αλ' : {a b : Atom}{M : Λ} → b # ƛ a M → ƛ a M ∼α ƛ b (( a ∙ b ) M)
lemma∼αλ' {a} {.a} {M} #ƛ≡ rewrite lemma(aa)M≡M {a} {M} = ρ
lemma∼αλ' (#ƛ b#M) = lemma∼αλ b#M
lemma#∼α : {a b : Atom}{M : Λ} → a # M → b # M → M ∼α ( a ∙ b ) M
lemma#∼α {a} {b} {v d} (#v d≢a) (#v d≢b)
rewrite lemma∙ₐc≢a∧c≢b d≢a d≢b = ρ
lemma#∼α {a} {b} {M · N} (#· a#M a#N) (#· b#M b#N)
= ∼α· (lemma#∼α a#M b#M) (lemma#∼α a#N b#N)
lemma#∼α {a} {b} {ƛ c M} a#ƛcM b#ƛcM
with a ≟ₐ c
lemma#∼α {a} {.a} {ƛ .a M} a#ƛaM #ƛ≡
| yes refl
rewrite lemma(aa)M≡M {a} {ƛ a M} = ρ
lemma#∼α {a} {b} {ƛ .a M} a#ƛaM (#ƛ b#M)
| yes refl
rewrite lemma∙ₐ(ab)a≡b {a} {b} = lemma∼αλ b#M
lemma#∼α {a} {b} {ƛ c M} a#ƛcM b#ƛcM
| no a≢c with b ≟ₐ c
lemma#∼α {.b} {b} {ƛ .b M} #ƛ≡ #ƛ≡
| no b≢b | yes refl = ⊥-elim (b≢b refl)
lemma#∼α {a} {b} {ƛ .b M} (#ƛ a#M) #ƛ≡
| no a≢b | yes refl
rewrite lemma∙ₐ(ab)b≡a {a} {b}
| lemma∙comm {a} {b} {M} = lemma∼αλ a#M
lemma#∼α {.b} {b} {ƛ .b M} #ƛ≡ (#ƛ b#M)
| no b≢b | yes refl = ⊥-elim (b≢b refl)
lemma#∼α {a} {b} {ƛ .b M} (#ƛ a#M) (#ƛ b#M)
| no a≢b | yes refl
rewrite lemma∙ₐ(ab)b≡a {a} {b}
| lemma∙comm {a} {b} {M} = lemma∼αλ a#M
lemma#∼α {a} {b} {ƛ c M} a#ƛcM b#ƛcM
| no a≢c | no b≢c
rewrite lemma∙ₐc≢a∧c≢b (sym≢ a≢c) (sym≢ b≢c)
= lemma∼αƛ (lemma#∼α (lemma#λ a≢c a#ƛcM) (lemma#λ b≢c b#ƛcM))
\end{code}
\begin{code}
αCompatiblePred : {l : Level} → (Λ → Set l) → Set l
αCompatiblePred P = {M N : Λ} → M ∼α N → P M → P N
\end{code}
\begin{code}
strong∼αCompatible : {l : Level}{A : Set l} → (Λ → A) → Λ → Set l
strong∼αCompatible f M = ∀ N → M ∼α N → f M ≡ f N
\end{code}