module IntegerAlgebra where open import Preliminaries open import Equivalences record IntAlg (X : Set) : Set where constructor mk-IntAlg field S : X ≅ X Z : X module _ {X : Set} (X-alg : IntAlg X) where private module X = IntAlg X-alg record DIntAlg (Y : X → Set) : Set where constructor mk-DIntAlg field S : {x : X} → Y x ≅ Y (X.S .fun x) Z : Y X.Z record Sec {Y : X → Set} (Y-alg : DIntAlg Y) : Set where private module Y = DIntAlg Y-alg field on-C : (x : X) → Y x on-S : (x : X) → on-C (X.S .fun x) ≡ Y.S .fun (on-C x) on-Z : on-C X.Z ≡ Y.Z nonDIntAlg : {Y : Set} (Y-alg : IntAlg Y) → DIntAlg (λ x → Y) nonDIntAlg Y-alg .DIntAlg.S = IntAlg.S Y-alg nonDIntAlg Y-alg .DIntAlg.Z = IntAlg.Z Y-alg postulate ℤ : Set ℤ-alg : IntAlg ℤ ℤ-elim : {Y : ℤ → Set} (Y-alg : DIntAlg ℤ-alg Y) → Sec ℤ-alg Y-alg module ℤ = IntAlg ℤ-alg module _ {P : ℤ → Set} (P-alg : DIntAlg ℤ-alg P) where private module P = DIntAlg P-alg abstract ℤ-ind : (x : ℤ) → P x ℤ-ind = Sec.on-C (ℤ-elim P-alg) ℤ-ind-S : (x : ℤ) → ℤ-ind (ℤ.S .fun x) ≡ P.S .fun (ℤ-ind x) ℤ-ind-S = Sec.on-S (ℤ-elim P-alg) ℤ-ind-Z : ℤ-ind ℤ.Z ≡ P.Z ℤ-ind-Z = Sec.on-Z (ℤ-elim P-alg) module _ {P : Set} (P-alg : IntAlg P) where module P = IntAlg P-alg abstract ℤ-elim-nondep : Sec ℤ-alg (nonDIntAlg ℤ-alg P-alg) ℤ-elim-nondep = ℤ-elim _ ℤ-rec : (x : ℤ) → P ℤ-rec = ℤ-ind $ nonDIntAlg _ P-alg ℤ-rec-S : (x : ℤ) → ℤ-rec (ℤ.S .fun x) ≡ P.S .fun (ℤ-rec x) ℤ-rec-S = ℤ-ind-S _ ℤ-rec-inv : (x : ℤ) → ℤ-rec (ℤ.S .inv x) ≡ P.S .inv (ℤ-rec x) ℤ-rec-inv x = symm (ap (P.S .inv ∘ ℤ-rec) (symm $ ℤ.S .fun-inv x) • ap (P.S .inv) (ℤ-rec-S _) • P.S .inv-fun _) ℤ-rec-Z : ℤ-rec ℤ.Z ≡ P.Z ℤ-rec-Z = ℤ-ind-Z _ ℤ-rec-uniq : {f g : ℤ → P} → ((x : ℤ) → f (ℤ.S .fun x) ≡ P.S .fun (f x)) → f ℤ.Z ≡ P.Z → ((x : ℤ) → g (ℤ.S .fun x) ≡ P.S .fun (g x)) → g ℤ.Z ≡ P.Z → (x : ℤ) → f x ≡ g x ℤ-rec-uniq {f} {g} fS fZ gS gZ = ℤ-ind $ mk-DIntAlg {Y = λ x → f x ≡ g x} (λ {x} → inv-iso (eq-congr (fS x) (gS x)) ∘ₑ ap-iso P.S) (fZ • symm gZ)