{-# OPTIONS --without-K --safe #-} module Cats.Util.SetoidMorphism.Iso where open import Data.Product using (_,_ ; proj₁ ; proj₂) open import Level using (_⊔_) open import Relation.Binary using (Setoid ; IsEquivalence) open import Cats.Util.SetoidMorphism as Mor using ( _⇒_ ; arr ; resp ; _≈_ ; ≈-intro ; ≈-elim ; ≈-elim′ ; _∘_ ; ∘-resp ; id ; IsInjective ; IsSurjective ) open import Cats.Util.SetoidReasoning private module S = Setoid record IsIso {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} (f : A ⇒ B) : Set (l ⊔ l≈ ⊔ l′ ⊔ l≈′) where field back : B ⇒ A forth-back : f ∘ back ≈ id back-forth : back ∘ f ≈ id open IsIso record _≅_ {l l≈} (A : Setoid l l≈) {l′ l≈′} (B : Setoid l′ l≈′) : Set (l ⊔ l≈ ⊔ l′ ⊔ l≈′) where field forth : A ⇒ B back : B ⇒ A forth-back : forth ∘ back ≈ id back-forth : back ∘ forth ≈ id open _≅_ public IsIso→≅ : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} (f : A ⇒ B) → IsIso f → A ≅ B IsIso→≅ f i = record { forth = f ; back = back i ; forth-back = forth-back i ; back-forth = back-forth i } ≅→IsIso : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → (i : A ≅ B) → IsIso (forth i) ≅→IsIso i = record { back = back i ; forth-back = forth-back i ; back-forth = back-forth i } IsIso-resp : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → {f g : A ⇒ B} → f ≈ g → IsIso f → IsIso g IsIso-resp {A = A} {B = B} {f} {g} f≈g i = record { back = back i ; forth-back = ≈-intro λ {x} {y} x≈y → begin⟨ B ⟩ arr g (arr (back i) x) ≈˘⟨ ≈-elim f≈g (resp (back i) (B.sym x≈y)) ⟩ arr f (arr (back i) y) ≈⟨ ≈-elim′ (forth-back i) ⟩ y ∎ ; back-forth = ≈-intro λ {x} {y} x≈y → begin⟨ A ⟩ arr (back i) (arr g x) ≈⟨ resp (back i) (B.sym (≈-elim f≈g (A.sym x≈y))) ⟩ arr (back i) (arr f y) ≈⟨ ≈-elim′ (back-forth i) ⟩ y ∎ } where module A = Setoid A module B = Setoid B refl : ∀ {l l≈} {A : Setoid l l≈} → A ≅ A refl = record { forth = id ; back = id ; forth-back = ≈-intro λ eq → eq ; back-forth = ≈-intro λ eq → eq } sym : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → A ≅ B → B ≅ A sym i = record { forth = back i ; back = forth i ; forth-back = back-forth i ; back-forth = forth-back i } trans : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → ∀ {l″ l≈″} {C : Setoid l″ l≈″} → A ≅ B → B ≅ C → A ≅ C trans {A = A} {C = C} AB BC = record { forth = forth BC ∘ forth AB ; back = back AB ∘ back BC ; forth-back = ≈-intro λ x≈y → S.trans C (resp (forth BC) (≈-elim (forth-back AB) (resp (back BC) x≈y))) (≈-elim′ (forth-back BC)) ; back-forth = ≈-intro λ x≈y → S.trans A (resp (back AB) (≈-elim (back-forth BC) (resp (forth AB) x≈y))) (≈-elim′ (back-forth AB)) } module _ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} where Injective∧Surjective→Iso : {f : A ⇒ B} → IsInjective f → IsSurjective f → IsIso f Injective∧Surjective→Iso {f} inj surj = record { back = record { arr = λ b → proj₁ (surj b) ; resp = λ {b} {c} b≈c → inj (S.trans B (S.sym B (proj₂ (surj b))) (S.trans B b≈c (proj₂ (surj c)))) } ; forth-back = ≈-intro λ {x} {y} x≈y → S.trans B (S.sym B (proj₂ (surj x))) x≈y ; back-forth = ≈-intro λ {x} {y} x≈y → inj (S.trans B (S.sym B (proj₂ (surj _))) (resp f x≈y)) } Injective∧Surjective→≅ : {f : A ⇒ B} → IsInjective f → IsSurjective f → A ≅ B Injective∧Surjective→≅ {f} inj surj = IsIso→≅ f (Injective∧Surjective→Iso inj surj) Iso→Injective : {f : A ⇒ B} → IsIso f → IsInjective f Iso→Injective {f} i {a} {b} fa≈fb = begin⟨ A ⟩ a ≈˘⟨ ≈-elim′ (back-forth i) ⟩ arr (back i) (arr f a) ≈⟨ resp (back i) fa≈fb ⟩ arr (back i) (arr f b) ≈⟨ ≈-elim′ (back-forth i) ⟩ b ∎ ≅-Injective : (i : A ≅ B) → IsInjective (forth i) ≅-Injective i = Iso→Injective (≅→IsIso i) Iso→Surjective : {f : A ⇒ B} → IsIso f → IsSurjective f Iso→Surjective i b = arr (back i) b , S.sym B (≈-elim′ (forth-back i)) ≅-Surjective : (i : A ≅ B) → IsSurjective (forth i) ≅-Surjective i = Iso→Surjective (≅→IsIso i)