---
layout: default
title : "Setoid.Homomorphisms.Basic module (Agda Universal Algebra Library)"
date : "2021-09-13"
author: "agda-algebras development team"
---

#### Homomorphisms of Algebras over Setoids

This is the [Setoid.Homomorphisms.Basic][] module of the [Agda Universal Algebra Library][].

A **homomorphism** from `𝑨` to `𝑩` is a setoid function `h : 𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]`
between the domains of the two algebras that is *compatible* with every basic
operation: for each operation symbol `f` and each tuple `a` of arguments,
`h ⟨$⟩ (f ^ 𝑨) a` and `(f ^ 𝑩) Ξ» x β†’ h ⟨$⟩ a x` are related by the equality of `𝑩`.

Two things distinguish this from an ordinary type-based definition, where
compatibility is an identification `h ((f ^ 𝑨) a) ≑ (f ^ 𝑩) (h ∘ a)`.

1.  The map is a setoid function, so it carries its own congruence proof and
    cannot fail to send equal arguments to equal results.
2.  Compatibility is asserted up to the equality *of the codomain*, not up to
    propositional equality; that is what lets `𝑩` be a quotient algebra (the same
    carrier under a coarser equivalence) with no special quotient type and no
    appeal to extensionality.

This module defines the compatibility predicates, the homomorphism type
`hom`{.AgdaFunction} and its predicate form `IsHom`{.AgdaRecord}, the injective
and surjective variants (monomorphisms and epimorphisms) in both of those forms,
the translations between them, and the identity homomorphism `𝒾𝒹`{.AgdaFunction}.
Everything else the library proves about homomorphisms is built on these,
including the following:

+  **composition**, `βŠ™-hom`{.AgdaFunction}, and the homomorphisms that witness
   **universe lifting** in [Setoid.Homomorphisms.Properties][];
+  **the kernel** of a homomorphism as a congruence, and the **quotient** it
   determines in [Setoid.Homomorphisms.Kernels][];
+  **isomorphism**, `_β‰…_`{.AgdaRecord}, given by a pair of mutually inverse
   homomorphisms in [Setoid.Homomorphisms.Isomorphisms][];
+  **the first homomorphism theorem** in [Setoid.Homomorphisms.Noether][];
+  **factoring** one homomorphism through another in
   [Setoid.Homomorphisms.Factor][].

<!--
```agda
{-# OPTIONS --cubical-compatible --exact-split --safe #-}

module Setoid.Homomorphisms.Basic  where

-- Imports from Agda and the Agda Standard Library ------------------------------
open import Agda.Primitive           using () renaming ( Set to Type )
open import Data.Product             using ( _,_ ; Ξ£ ; Ξ£-syntax ; proj₁ ; projβ‚‚ )
open import Function.Bundles         using () renaming ( Func to _⟢_ )
open import Level                    using ( Level ; _βŠ”_ )
open import Relation.Binary          using ( Setoid )
open import Relation.Binary.PropositionalEquality using ( refl )

-- Imports from the Agda Universal Algebra Library ---------------------------
open import Overture                 using ( OperationSymbolsOf ; π“ž ; π“₯ ; Signature )
open import Setoid.Functions         using ( IsInjective ; IsSurjective ; 𝑖𝑑 )
open import Setoid.Algebras          using ( Algebra ; _^_ ; 𝔻[_])

private variable
  Ξ± Ξ² ρᡃ ρᡇ : Level
```
-->

The homomorphism type is built in four steps.  `compatible-map-op`{.AgdaFunction}
says that a setoid function `h` commutes with *one* operation symbol `f`;
`compatible-map`{.AgdaFunction} quantifies that over all operation symbols;
`IsHom`{.AgdaRecord} packages the resulting property as a record with the single
field `compatible`{.AgdaField} and the constructor
`mkIsHom`{.AgdaInductiveConstructor}; and `hom`{.AgdaFunction} is the type of
homomorphisms proper.  An inhabitant of `hom 𝑨 𝑩` is therefore a pair `(h , p)`: a
setoid function `h` from the domain of `𝑨` to that of `𝑩`, together with a proof
that `h` is compatible.

`mkhom`{.AgdaFunction} is the smart constructor for that pair, so a caller who has
`h` and a `compatible-map`{.AgdaFunction} proof never has to write the `Ξ£`-pair
and the `IsHom`{.AgdaRecord} record by hand.

```agda
module _ {𝑆 : Signature π“ž π“₯} (𝑨 : Algebra {𝑆 = 𝑆} Ξ± ρᡃ)(𝑩 : Algebra Ξ² ρᡇ) where
  open _⟢_ {a = Ξ±}{ρᡃ}{Ξ²}{ρᡇ}{From = 𝔻[ 𝑨 ]}{To = 𝔻[ 𝑩 ]} renaming (to to _⟨$⟩_ )

  compatible-map-op : (𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) β†’ OperationSymbolsOf 𝑆 β†’ Type (π“₯ βŠ” Ξ± βŠ” ρᡇ)
  compatible-map-op h f =  βˆ€ {a} β†’ h ⟨$⟩ (f ^ 𝑨) a β‰ˆβ‚‚ (f ^ 𝑩) Ξ» x β†’ h ⟨$⟩ a x
    where open Setoid 𝔻[ 𝑩 ] using() renaming ( _β‰ˆ_ to _β‰ˆβ‚‚_ )

  compatible-map : (𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) β†’ Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡇ)
  compatible-map h = βˆ€ {f} β†’ compatible-map-op h f

  -- The property of being a homomorphism.
  record IsHom (h : 𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) : Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡃ βŠ” ρᡇ) where
    constructor mkIsHom
    field compatible : compatible-map h

  hom : Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡃ βŠ” Ξ² βŠ” ρᡇ)
  hom = Ξ£ (𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) IsHom

  -- Smart constructor for a homomorphism: bundle a setoid map with its
  -- compatibility proof, hiding the Ξ£ / IsHom plumbing.
  mkhom : (h : 𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) β†’ compatible-map h β†’ hom
  mkhom h c = h , mkIsHom c
```

#### Monomorphisms and epimorphisms

A **monomorphism** is an injective homomorphism and an **epimorphism** is a
surjective one.  Each comes in the two forms `hom`{.AgdaFunction} does:

+  the predicates `IsMon`{.AgdaRecord} and `IsEpi`{.AgdaRecord}, whose fields pair
   the homomorphism property with `IsInjective`{.AgdaFunction} or
   `IsSurjective`{.AgdaFunction};
+  the bundled types `mon`{.AgdaFunction} and `epi`{.AgdaFunction}, which pair a
   setoid function with such a proof.

Both predicates export a `HomReduct`{.AgdaFunction} that forgets the extra
condition, and `mon→hom`{.AgdaFunction} and `epi→hom`{.AgdaFunction} apply it to
the bundled forms.

`mon→intohom`{.AgdaFunction} and `epi→ontohom`{.AgdaFunction} regroup the same
data the other way, as a `hom`{.AgdaFunction} paired with the injectivity or the
surjectivity of its underlying map.  That regrouping earns a name because the two
resulting types are, by definition, `_IsSubalgebraOf_`{.AgdaFunction} of
[Setoid.Subalgebras.Basic][] and `_IsHomImageOf_`{.AgdaFunction} of
[Setoid.Homomorphisms.HomomorphicImages][]; so these are the functions that turn a
monomorphism into a subalgebra and an epimorphism into a homomorphic image.

```agda
  record IsMon (h : 𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) : Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡃ βŠ” Ξ² βŠ” ρᡇ) where
    field
      isHom : IsHom h
      isInjective : IsInjective h

    HomReduct : hom
    HomReduct = h , isHom

  mon : Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡃ βŠ” Ξ² βŠ” ρᡇ)
  mon = Ξ£ (𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) IsMon

  mon→hom : mon → hom
  mon→hom h = IsMon.HomReduct (proj₂ h)

  record IsEpi (h : 𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) : Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡃ βŠ” Ξ² βŠ” ρᡇ) where
    field
      isHom : IsHom h
      isSurjective : IsSurjective h

    HomReduct : hom
    HomReduct = h , isHom

  epi : Type (π“ž βŠ” π“₯ βŠ” Ξ± βŠ” ρᡃ βŠ” Ξ² βŠ” ρᡇ)
  epi = Ξ£ (𝔻[ 𝑨 ] ⟢ 𝔻[ 𝑩 ]) IsEpi

  epi→hom : epi → hom
  epi→hom h = IsEpi.HomReduct (proj₂ h)

module _ {𝑆 : Signature π“ž π“₯} (𝑨 : Algebra {𝑆 = 𝑆} Ξ± ρᡃ)(𝑩 : Algebra Ξ² ρᡇ) where
  open IsEpi
  open IsMon

  monβ†’intohom : mon 𝑨 𝑩 β†’ Ξ£[ h ∈ hom 𝑨 𝑩 ] IsInjective (proj₁ h)
  mon→intohom (hh , hhM) = (hh , isHom hhM) , isInjective hhM

  epiβ†’ontohom : epi 𝑨 𝑩 β†’ Ξ£[ h ∈ hom 𝑨 𝑩 ] IsSurjective (proj₁ h)
  epi→ontohom (hh , hhE) = (hh , isHom hhE) , isSurjective hhE
```

Finally, we define the identity homomorphism for setoid algebras.

```agda
module _ {𝑆 : Signature π“ž π“₯} {𝑨 : Algebra {𝑆 = 𝑆} Ξ± ρᡃ} where
  open Setoid 𝔻[ 𝑨 ]   using ( reflexive )

  𝒾𝒹 :  hom 𝑨 𝑨
  𝒾𝒹 = 𝑖𝑑 , mkIsHom (reflexive refl)
```