{-# OPTIONS --without-K --cubical-compatible #-}
open import common
module inductive-repair.indspec where
open _≃_
private
variable
ℓ : Level
data ConstrArity {ℓ : Level} : Type (lsuc ℓ) where
Done : ConstrArity
Nonrec : (A : Type ℓ) → (A → ConstrArity {ℓ}) → ConstrArity
Rec : (D : Type ℓ) → ConstrArity {ℓ} → ConstrArity
record Signature : Type (lsuc ℓ) where
field
Op : Type ℓ
arity : Op → ConstrArity {ℓ}
open Signature
Args : ConstrArity {ℓ} → Type ℓ → Type ℓ
Args Done _ = ⊤
Args (Nonrec A k) Ty = Σ A (λ a → Args (k a) Ty)
Args (Rec D cs) Ty = (D → Ty) × Args cs Ty
ConstrAlgebra : (sig : Signature {ℓ}) → (Ty : Type ℓ) → Type ℓ
ConstrAlgebra sig Ty = (c : Op sig) → Args (arity sig c) Ty → Ty
mapArgs : (cs : ConstrArity {ℓ}) {Ty₁ Ty₂ : Type ℓ} →
(Ty₁ → Ty₂) → Args cs Ty₁ → Args cs Ty₂
mapArgs Done f _ = tt
mapArgs (Nonrec A k) f (a , args) = (a , mapArgs (k a) f args)
mapArgs (Rec D cs) f (r , args) = (f ∘ r , mapArgs cs f args)
mapArgs-∘ : {Ty₁ Ty₂ Ty₃ : Type ℓ} (cs : ConstrArity {ℓ})
(f : Ty₁ → Ty₂) (g : Ty₂ → Ty₃) (args : Args cs Ty₁) →
mapArgs cs g (mapArgs cs f args) ≡ mapArgs cs (g ∘ f) args
mapArgs-∘ Done f g _ = refl
mapArgs-∘ (Nonrec A k) f g (a , args) = Σ-≡-intro refl (mapArgs-∘ (k a) f g args)
mapArgs-∘ (Rec D cs) f g (r , args) = Σ-≡-intro refl (mapArgs-∘ cs f g args)
IHs : (cs : ConstrArity {ℓ}) {Ty : Type ℓ} →
(motive : Ty → Type ℓ) → Args cs Ty → Type ℓ
IHs Done motive _ = ⊤
IHs (Nonrec A k) motive (a , args) = IHs (k a) motive args
IHs (Rec D cs) motive (r , args) = ((d : D) → motive (r d)) × IHs cs motive args
Cases : (sig : Signature {ℓ}) → (Ty : Type ℓ) →
ConstrAlgebra sig Ty → (motive : Ty → Type ℓ) → Type ℓ
Cases sig Ty algebra motive =
(c : Op sig) → (args : Args (arity sig c) Ty) →
(ih : IHs (arity sig c) motive args) → motive (algebra c args)
Induction : {Ty : Type ℓ} → (sig : Signature {ℓ}) →
(algebra : ConstrAlgebra sig Ty) → Type (lsuc ℓ)
Induction {Ty = Ty} sig algebra = (motive : Ty → Type _) →
Cases sig Ty algebra motive → (a : Ty) → motive a
mkIHs : (cs : ConstrArity {ℓ}) {Ty : Type ℓ} {motive : Ty → Type ℓ} →
(elim : (a : Ty) → motive a) → (args : Args cs Ty) →
IHs cs motive args
mkIHs Done elim _ = tt
mkIHs (Nonrec A k) elim (a , args) = mkIHs (k a) elim args
mkIHs (Rec D cs) elim (r , args) = ((λ d → elim (r d)) , mkIHs cs elim args)
BetaLaw : {Ty : Type ℓ} → (sig : Signature {ℓ}) → {algebra : ConstrAlgebra sig Ty} →
(induction : Induction sig algebra) → Type (lsuc ℓ)
BetaLaw {Ty = Ty} sig {algebra} induction =
(motive : Ty → Type _) → (cases : Cases sig Ty algebra motive) →
(c : Op sig) → (args : Args (arity sig c) Ty) →
induction motive cases (algebra c args)
≡ cases c args (mkIHs (arity sig c) (induction motive cases) args)
EtaLaw : {Ty : Type ℓ} (sig : Signature {ℓ}) →
{algebra : ConstrAlgebra sig Ty} → (induction : Induction sig algebra) → Type ℓ
EtaLaw {Ty = Ty} sig {algebra} induction = (x : Ty) →
Σ (Op sig) (λ c → Σ (Args (arity sig c) Ty) (λ args → algebra c args ≡ x))
setRec : (cs : ConstrArity {ℓ}) {Ty₁ Ty₂ : Type ℓ} →
(args : Args cs Ty₁) → IHs cs (λ _ → Ty₂) args →
Args cs Ty₂
setRec Done _ _ = tt
setRec (Nonrec A k) (a , args) ih = (a , setRec (k a) args ih)
setRec (Rec D cs) (r , args) (r' , ih) = (r' , setRec cs args ih)
setRec-mkIHs : {Ty₁ Ty₂ : Type ℓ} (cs : ConstrArity {ℓ})
(f : Ty₁ → Ty₂) (args : Args cs Ty₁) →
setRec cs args (mkIHs cs f args) ≡ mapArgs cs f args
setRec-mkIHs Done f _ = refl
setRec-mkIHs (Nonrec A k) f (a , args) = Σ-≡-intro refl (setRec-mkIHs (k a) f args)
setRec-mkIHs (Rec D cs) f (r , args) = Σ-≡-intro refl (setRec-mkIHs cs f args)
record IndAlg (sig : Signature {ℓ}) (C : Type ℓ) : Type (lsuc ℓ) where
field
algebra : ConstrAlgebra sig C
ind : Induction sig algebra
beta : BetaLaw sig ind
fold : {D : Type ℓ} → ConstrAlgebra sig D → C → D
fold algD =
ind (λ _ → _) λ c argsC ih → algD c (setRec (arity sig c) argsC ih)
fold-β : {D : Type ℓ} (algD : ConstrAlgebra sig D)
(c : Op sig) (argsC : Args (arity sig c) C) →
fold algD (algebra c argsC)
≡ algD c (mapArgs (arity sig c) (fold algD) argsC)
fold-β algD c argsC =
beta (λ _ → _) (λ c' args' ih → algD c' (setRec (arity sig c') args' ih)) c argsC
• ap (algD c) (setRec-mkIHs (arity sig c) (fold algD) argsC)
eta : EtaLaw sig ind
eta = ind _ (λ c args _ → c , args , refl)
mapArgs-id-pw : {Ty : Type ℓ} (cs : ConstrArity {ℓ}) (f : Ty → Ty) →
(args : Args cs Ty) → IHs cs (λ x → f x ≡ x) args →
mapArgs cs f args ≡ args
mapArgs-id-pw Done f _ _ = refl
mapArgs-id-pw (Nonrec A k) f (a , args) ih =
Σ-≡-intro refl (mapArgs-id-pw (k a) f args ih)
mapArgs-id-pw (Rec D cs) f (r , args) (ih-h , ih-t) =
Σ-≡-intro (ext ih-h) (tptConst (ext ih-h) _ • mapArgs-id-pw cs f args ih-t)
mapArgs-cong-pw : {Ty₁ Ty₂ : Type ℓ} (cs : ConstrArity {ℓ}) (f₁ f₂ : Ty₁ → Ty₂)
(args : Args cs Ty₁) → IHs cs (λ x → f₁ x ≡ f₂ x) args →
mapArgs cs f₁ args ≡ mapArgs cs f₂ args
mapArgs-cong-pw Done f₁ f₂ _ _ = refl
mapArgs-cong-pw (Nonrec A k) f₁ f₂ (a , args) ih =
Σ-≡-intro refl (mapArgs-cong-pw (k a) f₁ f₂ args ih)
mapArgs-cong-pw (Rec D cs) f₁ f₂ (r , args) (ih-h , ih-t) =
ap2 _,_ (ext ih-h) (mapArgs-cong-pw cs f₁ f₂ args ih-t)
mapArgs-eqv : (cs : ConstrArity {ℓ}) {A B : Type ℓ} →
A ≃ B → Args cs A ≃ Args cs B
mapArgs-eqv Done _ = id-eqv
mapArgs-eqv (Nonrec T k) eqv = Σ-eqv-snd (λ t → mapArgs-eqv (k t) eqv)
mapArgs-eqv (Rec D cs) eqv = ×-eqv (→-eqv-r eqv) (mapArgs-eqv cs eqv)
mapArgs-eqv-f : (cs : ConstrArity {ℓ}) {A B : Type ℓ} (eqv : A ≃ B) (args : Args cs A) →
f (mapArgs-eqv cs eqv) args ≡ mapArgs cs (f eqv) args
mapArgs-eqv-f Done eqv _ = refl
mapArgs-eqv-f (Nonrec T k) eqv (t , args) = ap (λ x → (t , x)) (mapArgs-eqv-f (k t) eqv args)
mapArgs-eqv-f (Rec D cs) eqv (r , args) = ap (λ x → (f eqv ∘ r , x)) (mapArgs-eqv-f cs eqv args)
mapArgs-id : {Ty : Type ℓ} (cs : ConstrArity {ℓ}) (args : Args cs Ty) →
mapArgs cs (λ x → x) args ≡ args
mapArgs-id Done _ = refl
mapArgs-id (Nonrec A k) (a , args) = ap (λ x → (a , x)) (mapArgs-id (k a) args)
mapArgs-id (Rec D cs) (r , args) = ap (λ x → (r , x)) (mapArgs-id cs args)
fold-roundtrip : {sig : Signature {ℓ}} {C D : Type ℓ} →
(A : IndAlg sig C) (B : IndAlg sig D) →
(x : C) → IndAlg.fold B (IndAlg.algebra A)
(IndAlg.fold A (IndAlg.algebra B) x) ≡ x
fold-roundtrip {sig = sig} A B = indA (λ x → foldB algA (foldA algB x) ≡ x)
λ c args ih →
ap (foldB algA) (foldA-β algB c args)
• foldB-β algA c (mapArgs (arity sig c) (foldA algB) args)
• ap (algA c) (mapArgs-∘ (arity sig c) (foldA algB) (foldB algA) args
• mapArgs-id-pw (arity sig c) (foldB algA ∘ foldA algB) args ih)
where
open IndAlg A renaming (algebra to algA; ind to indA; fold to foldA; fold-β to foldA-β)
open IndAlg B renaming (algebra to algB; fold to foldB; fold-β to foldB-β)
fold-unique : {sig : Signature {ℓ}} {C D : Type ℓ} (ialg : IndAlg sig C)
(algD : ConstrAlgebra sig D) (h : C → D) →
((c : Op sig) (args : Args (arity sig c) C) →
h (IndAlg.algebra ialg c args)
≡ algD c (mapArgs (arity sig c) h args)) →
(x : C) → h x ≡ IndAlg.fold ialg algD x
fold-unique {sig = sig} ialg algD h hom =
ind (λ x → h x ≡ fold algD x)
(λ c args ih →
hom c args
• ap (algD c) (mapArgs-cong-pw (arity sig c) h (fold algD) args ih)
• ! (fold-β algD c args))
where open IndAlg ialg
mkIHs-cong : {Ty : Type ℓ} {motive : Ty → Type ℓ} (cs : ConstrArity {ℓ})
(e1 e2 : (a : Ty) → motive a) (args : Args cs Ty) →
IHs cs (λ x → e1 x ≡ e2 x) args →
mkIHs cs e1 args ≡ mkIHs cs e2 args
mkIHs-cong Done e1 e2 _ _ = refl
mkIHs-cong (Nonrec A k) e1 e2 (a , args) ih =
mkIHs-cong (k a) e1 e2 args ih
mkIHs-cong (Rec D cs) e1 e2 (r , args) (ih-h , ih-t) =
ap2 _,_ (ext ih-h) (mkIHs-cong cs e1 e2 args ih-t)
ind-unique : {sig : Signature {ℓ}} {C : Type ℓ} (ialg : IndAlg sig C)
(i' : Induction sig (IndAlg.algebra ialg)) → BetaLaw sig i' →
(motive : C → Type ℓ)
(cases : Cases sig C (IndAlg.algebra ialg) motive) →
(a : C) → IndAlg.ind ialg motive cases a ≡ i' motive cases a
ind-unique {sig = sig} ialg i' b' motive cases =
IndAlg.ind ialg
(λ a → IndAlg.ind ialg motive cases a ≡ i' motive cases a)
(λ c args ih →
IndAlg.beta ialg motive cases c args
• ap (cases c args)
(mkIHs-cong (arity sig c)
(IndAlg.ind ialg motive cases)
(i' motive cases) args ih)
• ! (b' motive cases c args))