{-# OPTIONS --without-K --safe #-} module Cats.Util.SetoidMorphism where open import Data.Product using (∃-syntax ; _,_ ; proj₁ ; proj₂) open import Level using (_⊔_ ; suc) open import Relation.Binary using (Rel ; Setoid ; IsEquivalence ; _Preserves_⟶_) open import Relation.Binary.SetoidReasoning open import Cats.Util.Function using () renaming (_∘_ to _⊚_) open Setoid renaming (_≈_ to eq) infixr 9 _∘_ record _⇒_ {l l≈} (A : Setoid l l≈) {l′ l≈′} (B : Setoid l′ l≈′) : Set (l ⊔ l′ ⊔ l≈ ⊔ l≈′) where field arr : Carrier A → Carrier B resp : arr Preserves eq A ⟶ eq B open _⇒_ public using (arr ; resp) module _ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} where infixr 4 _≈_ record _≈_ (f g : A ⇒ B) : Set (l ⊔ l≈ ⊔ l≈′) where constructor ≈-intro field ≈-elim : ∀ {x y} → eq A x y → eq B (arr f x) (arr g y) ≈-elim′ : ∀ {x} → eq B (arr f x) (arr g x) ≈-elim′ = ≈-elim (refl A) open _≈_ public equiv : IsEquivalence _≈_ equiv = record { refl = λ {f} → ≈-intro (resp f) ; sym = λ eq → ≈-intro λ x≈y → sym B (≈-elim eq (sym A x≈y)) ; trans = λ eq₁ eq₂ → ≈-intro (λ x≈y → trans B (≈-elim eq₁ x≈y) (≈-elim′ eq₂)) } setoid : Setoid (l ⊔ l≈ ⊔ l′ ⊔ l≈′) (l ⊔ l≈ ⊔ l≈′) setoid = record { Carrier = A ⇒ B ; _≈_ = _≈_ ; isEquivalence = equiv } id : ∀ {l l≈} {A : Setoid l l≈} → A ⇒ A id = record { arr = λ x → x ; resp = λ x → x } _∘_ : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → ∀ {l″ l≈″} {C : Setoid l″ l≈″} → B ⇒ C → A ⇒ B → A ⇒ C _∘_ f g = record { arr = arr f ⊚ arr g ; resp = resp f ⊚ resp g } ∘-resp : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → ∀ {l″ l≈″} {C : Setoid l″ l≈″} → {f f′ : B ⇒ C} {g g′ : A ⇒ B} → f ≈ f′ → g ≈ g′ → f ∘ g ≈ f′ ∘ g′ ∘-resp f≈f′ g≈g′ = ≈-intro (≈-elim f≈f′ ⊚ ≈-elim g≈g′) id-l : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → {f : A ⇒ B} → id ∘ f ≈ f id-l {f = f} = ≈-intro (resp f) id-r : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → {f : A ⇒ B} → f ∘ id ≈ f id-r {f = f} = ≈-intro (resp f) assoc : ∀ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} → ∀ {l″ l≈″} {C : Setoid l″ l≈″} {l‴ l≈‴} {D : Setoid l‴ l≈‴} → {f : C ⇒ D} {g : B ⇒ C} {h : A ⇒ B} → (f ∘ g) ∘ h ≈ f ∘ (g ∘ h) assoc {f = f} {g} {h} = ≈-intro (resp f ⊚ resp g ⊚ resp h) module _ {l l≈} {A : Setoid l l≈} {l′ l≈′} {B : Setoid l′ l≈′} where IsInjective : A ⇒ B → Set (l ⊔ l≈ ⊔ l≈′) IsInjective f = ∀ {a b} → eq B (arr f a) (arr f b) → eq A a b IsSurjective : A ⇒ B → Set (l ⊔ l′ ⊔ l≈′) IsSurjective f = ∀ b → ∃[ a ] (eq B b (arr f a))