open import Action
open import Relation.Binary.Core using (Rel)
open import Relation.Binary.Definitions using (DecidableEquality)
open import Relation.Binary.PropositionalEquality hiding ([_] ; subst)
open ≡-Reasoning
open import Function
module Syntax {ℓ} (A : Set ℓ) {dec : DecidableEquality A} {Action : Act A dec} where
open Act Action
open Action.Renaming A dec Action
open import Data.Nat
open import Data.Nat.Properties
open import Data.Fin using (Fin ; raise)
infix 20 _∣_
infix 21 _+_
infix 25 _∙_
infix 25 #_
data Proc : ℕ → Set ℓ where
∅ : ∀ {n} → Proc n
#_ : ∀ {n} →
(x : Fin n) →
Proc n
_∙_ : ∀ {n} →
(α : Aτ) →
(P : Proc n) →
Proc n
_+_ : ∀ {n} →
(P Q : Proc n) →
Proc n
_∣_ : ∀ {n} →
(P Q : Proc n) →
Proc n
_∖_ : ∀ {n} →
(P : Proc n) →
(a : A) →
Proc n
_[_] : ∀ {n} →
(P : Proc n) →
(φ : Renaming) →
Proc n
fix : ∀ {n} →
(P : Proc (suc n)) →
Proc n
ext : ∀ {n m} → (ρ : Fin n → Fin m) → Fin (suc n) → Fin (suc m)
ext ρ Fin.zero = Fin.zero
ext ρ (Fin.suc x) = Fin.suc (ρ x)
rename : ∀ {n m} → (ρ : Fin n → Fin m) → Proc n → Proc m
rename ρ ∅ = ∅
rename ρ (# x) = # (ρ x)
rename ρ (α ∙ P) = α ∙ (rename ρ P)
rename ρ (P + Q) = (rename ρ P) + (rename ρ Q)
rename ρ (P ∣ Q) = (rename ρ P) ∣ (rename ρ Q)
rename ρ (P ∖ a) = (rename ρ P) ∖ a
rename ρ (P [ φ ]) = (rename ρ P) [ φ ]
rename ρ (fix P) = fix (rename (ext ρ) P)
exts : ∀ {n m} → (σ : Fin n → Proc m) → Fin (suc n) → Proc (suc m)
exts σ Fin.zero = # Fin.zero
exts σ (Fin.suc x) = rename Fin.suc (σ x)
subst : ∀ {n m} → (σ : Fin n → Proc m) → Proc n → Proc m
subst σ ∅ = ∅
subst σ (# x) = σ x
subst σ (α ∙ P) = α ∙ subst σ P
subst σ (P + Q) = subst σ P + subst σ Q
subst σ (P ∣ Q) = subst σ P ∣ subst σ Q
subst σ (P ∖ a) = subst σ P ∖ a
subst σ (P [ φ ]) = subst σ P [ φ ]
subst σ (fix P) = fix (subst (exts σ) P)
subst-zero : {n : ℕ} → Proc n → Fin (suc n) → Proc n
subst-zero Q Fin.zero = Q
subst-zero Q (Fin.suc x) = # x
_[0↦_] : ∀ {n} → Proc (suc n) → Proc n → Proc n
_[0↦_] {n} P Q = subst (subst-zero Q) P
_[1↦_] : ∀ {n} → Proc (suc (suc n)) → Proc n → Proc (suc n)
_[1↦_] {n} P Q = subst (exts (subst-zero Q)) P
_↑ : ∀ {n} → Proc n → Proc (suc n)
P ↑ = rename Fin.suc P
Subst : ℕ → ℕ → Set ℓ
Subst n m = Fin n → Proc m
⟪_⟫ : ∀ {n m} → Subst n m → Proc n → Proc m
⟪ σ ⟫ M = subst σ M
ids : ∀ {n} → Subst n n
ids n = # n
↑ : ∀ {n} → Subst n (suc n)
↑ x = # (Fin.suc x)
infixr 6 _⊙_
_⊙_ : ∀ {n m} → Proc m → Subst n m → Subst (suc n) m
(M ⊙ σ) Fin.zero = M
(M ⊙ σ) (Fin.suc x) = σ x
infixr 5 _⨾_
_⨾_ : ∀ {n m p} → Subst n m → Subst m p → Subst n p
(σ ⨾ τ) x = ⟪ τ ⟫ (σ x)
sub-zero : ∀ {n m} {P : Proc m} {σ : Subst n m} →
⟪ P ⊙ σ ⟫ (# Fin.zero) ≡ P
sub-zero = refl
sub-suc : ∀ {n m} {P : Proc m} {σ : Subst n m} →
(↑ ⨾ P ⊙ σ) ≡ σ
sub-suc = refl
subst-Z-cons-ids : ∀ {n} {P : Proc n} →
subst-zero P ≗ (P ⊙ ids)
subst-Z-cons-ids Fin.zero = refl
subst-Z-cons-ids (Fin.suc x) = refl
sub-dist : ∀ {n m p} {σ : Subst n m} {σ' : Subst m p} {P : Proc m} →
(P ⊙ σ) ⨾ σ' ≗ ⟪ σ' ⟫ P ⊙ (σ ⨾ σ')
sub-dist Fin.zero = refl
sub-dist (Fin.suc x) = refl
cong-ext : ∀ {n m} {σ σ' : Fin n → Fin m} →
σ ≗ σ' → ext σ ≗ ext σ'
cong-ext eq Fin.zero = refl
cong-ext eq (Fin.suc x) = cong Fin.suc (eq x)
cong-rename : ∀ {n m} {ρ ρ' : Fin n → Fin m} →
ρ ≗ ρ' →
rename ρ ≗ rename ρ'
cong-rename eq ∅ = refl
cong-rename eq (# x) = cong #_ (eq x)
cong-rename eq (α ∙ P) = cong (α ∙_) (cong-rename eq P)
cong-rename eq (P + Q) = cong₂ _+_ (cong-rename eq P) (cong-rename eq Q)
cong-rename eq (P ∣ Q) = cong₂ _∣_ (cong-rename eq P) (cong-rename eq Q)
cong-rename eq (P ∖ a) = cong (_∖ a) (cong-rename eq P)
cong-rename eq (P [ φ ]) = cong (_[ φ ]) (cong-rename eq P)
cong-rename eq (fix P) = cong fix (cong-rename (cong-ext eq) P)
compose-rename : ∀ {n m p} {ρ : Fin m → Fin p} {ρ' : Fin n → Fin m} →
rename ρ ∘ rename ρ' ≗ rename (ρ ∘ ρ')
compose-rename ∅ = refl
compose-rename (# x) = refl
compose-rename (α ∙ P) = cong (α ∙_) (compose-rename P)
compose-rename (P + Q) = cong₂ _+_ (compose-rename P) (compose-rename Q)
compose-rename (P ∣ Q) = cong₂ _∣_ (compose-rename P) (compose-rename Q)
compose-rename (P ∖ a) = cong (_∖ a) (compose-rename P)
compose-rename (P [ φ ]) = cong (_[ φ ]) (compose-rename P)
compose-rename (fix P)
= cong fix (trans (compose-rename P)
(cong-rename (λ{ Fin.zero → refl ; (Fin.suc x) → refl}) P))
commute-subst-rename : ∀ {n m} {σ : Subst n m}
{ρ₁ : Fin n → Fin (suc n)} {ρ₂ : Fin m → Fin (suc m)} →
(exts σ) ∘ ρ₁ ≗ rename ρ₂ ∘ σ →
subst (exts σ) ∘ (rename ρ₁) ≗ rename ρ₂ ∘ subst σ
commute-subst-rename eq ∅ = refl
commute-subst-rename eq (# x) = eq x
commute-subst-rename eq (α ∙ P) = cong (α ∙_) (commute-subst-rename eq P)
commute-subst-rename eq (P + Q) = cong₂ _+_ (commute-subst-rename eq P) (commute-subst-rename eq Q)
commute-subst-rename eq (P ∣ Q) = cong₂ _∣_ (commute-subst-rename eq P) (commute-subst-rename eq Q)
commute-subst-rename eq (P ∖ a) = cong (_∖ a) (commute-subst-rename eq P)
commute-subst-rename eq (P [ φ ]) = cong (_[ φ ]) (commute-subst-rename eq P)
commute-subst-rename {σ = σ} {ρ₁ = ρ₁} {ρ₂ = ρ₂} eq (fix P) = cong fix (commute-subst-rename lemma P)
where lemma : exts (exts σ) ∘ ext ρ₁ ≗ rename (ext ρ₂) ∘ exts σ
lemma Fin.zero = refl
lemma (Fin.suc x) = begin
(exts (exts σ) ∘ ext ρ₁) (Fin.suc x)
≡⟨ cong (rename Fin.suc) (eq x) ⟩
rename Fin.suc (rename ρ₂ (σ x))
≡⟨ compose-rename (σ x) ⟩
rename (λ z → Fin.suc (ρ₂ z)) (σ x)
≡⟨ sym (compose-rename (σ x)) ⟩
(rename (ext ρ₂) ∘ exts σ) (Fin.suc x) ∎
exts-seq : ∀ {n m p} {σ : Subst n m} {σ' : Subst m p} →
(exts σ ⨾ exts σ') ≗ exts (σ ⨾ σ')
exts-seq Fin.zero = refl
exts-seq {σ = σ} (Fin.suc x) = commute-subst-rename (λ _ → refl) (σ x)
subst-ext : ∀ {n m} → {σ σ' : Fin n → Proc m} →
σ ≗ σ' → subst σ ≗ subst σ'
subst-ext eqσ ∅ = refl
subst-ext eqσ (# x) = eqσ x
subst-ext eqσ (α ∙ P) = cong (α ∙_) (subst-ext eqσ P)
subst-ext eqσ (P + Q) = cong₂ _+_ (subst-ext eqσ P) (subst-ext eqσ Q)
subst-ext eqσ (P ∣ Q) = cong₂ _∣_ (subst-ext eqσ P) (subst-ext eqσ Q)
subst-ext eqσ (P ∖ a) = cong (_∖ a) (subst-ext eqσ P)
subst-ext eqσ (P [ φ ]) = cong (_[ φ ]) (subst-ext eqσ P)
subst-ext eqσ (fix P)
= cong fix (subst-ext
(λ { Fin.zero → refl ;
(Fin.suc x) → cong (rename Fin.suc) (eqσ x) })
P)
cong-sub : ∀ {n m} {σ σ' : Subst n m} {P P' : Proc n} →
(σ ≗ σ') → P ≡ P' → ⟪ σ ⟫ P ≡ ⟪ σ' ⟫ P'
cong-sub {P = P} eq refl = subst-ext eq P
rename-subst-ren : ∀ {n m} {ρ : Fin n → Fin m}
→ rename ρ ≗ ⟪ ids ∘ ρ ⟫
rename-subst-ren ∅ = refl
rename-subst-ren (# x) = refl
rename-subst-ren (α ∙ P) = cong (α ∙_) (rename-subst-ren P)
rename-subst-ren (P + Q) = cong₂ _+_ (rename-subst-ren P) (rename-subst-ren Q)
rename-subst-ren (P ∣ Q) = cong₂ _∣_ (rename-subst-ren P) (rename-subst-ren Q)
rename-subst-ren (P ∖ a) = cong (_∖ a) (rename-subst-ren P)
rename-subst-ren (P [ φ ]) = cong (_[ φ ]) (rename-subst-ren P)
rename-subst-ren (fix P)
= trans (cong fix (rename-subst-ren P))
(cong fix (cong-sub {P = P}
(λ{ Fin.zero → refl ; (Fin.suc x) → refl})
refl))
exts-suc-shift : ∀ {n m} {σ : Subst n m} →
exts σ ≗ (# Fin.zero ⊙ (σ ⨾ ↑))
exts-suc-shift Fin.zero = refl
exts-suc-shift {σ = σ} (Fin.suc x) = rename-subst-ren (σ x)
cong-cons : ∀ {n m} {P Q : Proc m} {σ σ' : Subst n m} →
P ≡ Q → σ ≗ σ' →
(P ⊙ σ) ≗ (Q ⊙ σ')
cong-cons refl eq Fin.zero = refl
cong-cons refl eq (Fin.suc x) = eq x
cong-seq : ∀ {n m p} {σ σ' : Subst n m} {τ τ' : Subst m p}
→ σ ≗ σ' → τ ≗ τ'
→ (σ ⨾ τ) ≗ (σ' ⨾ τ')
cong-seq {σ' = σ'} {τ = τ} eqσ eqτ x
= trans (cong (subst τ) (eqσ x))
(cong-sub {P = σ' x} eqτ refl)
sub-id : ∀ {n} (P : Proc n) → ⟪ ids ⟫ P ≡ P
sub-id ∅ = refl
sub-id (# x) = refl
sub-id (α ∙ P) = cong (α ∙_) (sub-id P)
sub-id (P + Q) = cong₂ _+_ (sub-id P) (sub-id Q)
sub-id (P ∣ Q) = cong₂ _∣_ (sub-id P) (sub-id Q)
sub-id (P ∖ a) = cong (_∖ a) (sub-id P)
sub-id (P [ φ ]) = cong (_[ φ ]) (sub-id P)
sub-id (fix P)
= trans (cong fix (cong-sub {P = P}
(λ { Fin.zero → refl ; (Fin.suc x) → refl }) refl))
(cong fix (sub-id P))
sub-idR : ∀ {n m} {σ : Subst n m} → (σ ⨾ ids) ≗ σ
sub-idR {σ = σ} x = sub-id (σ x)
sub-idL : ∀ {n m} {σ : Subst n m} → (ids ⨾ σ) ≗ σ
sub-idL x = refl
sub-sub : ∀ {n m p} {P : Proc n} {σ : Subst n m} {σ' : Subst m p} →
⟪ σ' ⟫ (⟪ σ ⟫ P) ≡ ⟪ σ ⨾ σ' ⟫ P
sub-sub {P = ∅} = refl
sub-sub {P = # x} = refl
sub-sub {P = α ∙ P} = cong (α ∙_) (sub-sub {P = P})
sub-sub {P = P + Q} = cong₂ _+_ (sub-sub {P = P}) (sub-sub {P = Q})
sub-sub {P = P ∣ Q} = cong₂ _∣_ (sub-sub {P = P}) (sub-sub {P = Q})
sub-sub {P = P ∖ a} = cong (_∖ a) (sub-sub {P = P})
sub-sub {P = P [ φ ]} = cong (_[ φ ]) (sub-sub {P = P})
sub-sub {P = fix P} {σ} {σ'} = begin
⟪ σ' ⟫ (⟪ σ ⟫ (fix P)) ≡⟨⟩
fix (⟪ exts σ' ⟫ (⟪ exts σ ⟫ P)) ≡⟨ cong fix (sub-sub {P = P} {σ = exts σ} {σ' = exts σ'}) ⟩
fix (⟪ exts σ ⨾ exts σ' ⟫ P) ≡⟨ cong fix (cong-sub {P = P} exts-seq refl) ⟩
fix (⟪ exts (σ ⨾ σ') ⟫ P) ∎
sub-assoc : ∀ {n m p q} {σ : Subst n m} {τ : Subst m p} {θ : Subst p q} →
(σ ⨾ τ) ⨾ θ ≗ σ ⨾ τ ⨾ θ
sub-assoc {σ = σ} x = sub-sub {P = σ x}
subst-commute : ∀ {n m} {P : Proc (suc (suc n))} {Q : Proc (suc n)} {σ : Subst (suc n) m } →
⟪ exts σ ⟫ P [0↦ ⟪ σ ⟫ Q ] ≡ ⟪ σ ⟫ (P [0↦ Q ])
subst-commute {n} {m} {P} {Q} {σ} = begin
subst (subst-zero (subst σ Q)) (subst (exts σ) P)
≡⟨ cong-sub {P = ⟪ exts σ ⟫ P} subst-Z-cons-ids refl ⟩
subst (subst σ Q ⊙ #_) (subst (exts σ) P)
≡⟨ sub-sub {P = P} ⟩
subst (exts σ ⨾ (subst σ Q ⊙ #_)) P
≡⟨ cong-sub {P = P} (cong-seq exts-suc-shift λ _ → refl) refl ⟩
subst (((# Fin.zero) ⊙ (σ ⨾ (λ z → # Fin.suc z))) ⨾ (subst σ Q ⊙ #_)) P
≡⟨ cong-sub {P = P} sub-dist refl ⟩
⟪ ⟪ σ ⟫ Q ⊙ ((σ ⨾ ↑) ⨾ (⟪ σ ⟫ Q ⊙ ids)) ⟫ P
≡⟨ cong-sub {P = P} (cong-cons refl (sub-assoc {σ = σ})) refl ⟩
⟪ ⟪ σ ⟫ Q ⊙ (σ ⨾ ↑ ⨾ (⟪ σ ⟫ Q) ⊙ ids) ⟫ P
≡⟨ cong-sub {P = P} (λ _ → refl) refl ⟩
⟪ ⟪ σ ⟫ Q ⊙ (σ ⨾ ids) ⟫ P
≡⟨ cong-sub {P = P} (cong-cons refl (sub-idR {σ = σ})) refl ⟩
⟪ ⟪ σ ⟫ Q ⊙ σ ⟫ P
≡⟨ cong-sub {P = P} (cong-cons refl (sub-idL {σ = σ})) refl ⟩
⟪ ⟪ σ ⟫ Q ⊙ (ids ⨾ σ) ⟫ P
≡⟨ cong-sub {P = P} (sym ∘ sub-dist) refl ⟩
⟪ (Q ⊙ ids) ⨾ σ ⟫ P
≡⟨ sym (sub-sub {P = P}) ⟩
⟪ σ ⟫ (⟪ Q ⊙ ids ⟫ P)
≡⟨ cong ⟪ σ ⟫ (sym (cong-sub {P = P} subst-Z-cons-ids refl)) ⟩
⟪ σ ⟫ (P [0↦ Q ]) ∎
fin-cast : (n m : ℕ) → Fin n → Fin (n ⊔ m)
fin-cast n m x = Data.Fin.inject≤ x (m≤m⊔n n m)
max-cast : (n m : ℕ) → Proc n → Proc (n ⊔ m)
max-cast n m ∅ = ∅
max-cast n m (# x) = # (fin-cast n m x)
max-cast n m (α ∙ P) = α ∙ max-cast n m P
max-cast n m (P + Q) = (max-cast n m P) + (max-cast n m Q)
max-cast n m (P ∣ Q) = (max-cast n m P) ∣ max-cast n m Q
max-cast n m (P ∖ a) = (max-cast n m P) ∖ a
max-cast n m (P [ φ ]) = (max-cast n m P) [ φ ]
max-cast n m (fix P) = fix (max-cast (suc n) (suc m) P)
open import Relation.Binary.PropositionalEquality renaming (subst to ≡-subst)
max-cast' : (n m : ℕ) → Proc m → Proc (n ⊔ m)
max-cast' n m P = ≡-subst Proc (⊔-comm m n) (max-cast m n P)