Skip to content

Setoid.Categories.Functor

Functors between minimal categories

This is the Setoid.Categories.Functor module of the Agda Universal Algebra Library.

A functor is a structure-preserving translation between categories โ€” the categorical analog of a homomorphism. Where a homomorphism of algebras carries elements to elements while preserving the operations, a Functor ๐‚ ๐ƒ carries the objects of ๐‚ to objects of ๐ƒ (the object map Fโ‚€) and the morphisms of ๐‚ to morphisms of ๐ƒ (the hom map Fโ‚), while preserving the only structure a category has: identities and composition. Those two preservation conditions are the functor laws identity and homomorphism, and โ€” as everywhere in this layer โ€” they are stated up to the target category's hom-equality _โ‰ˆ_, so a category whose hom-equality is pointwise can prove them pointwise, without function extensionality.

Why insist on the laws, rather than taking any pair of maps (Fโ‚€ , Fโ‚)? Because the laws are what make diagram-chasing arguments transport along F: a commuting diagram in ๐‚ is a tower of composites, and homomorphism is exactly the license to push F through each composite, corner by corner. The third field, F-resp-โ‰ˆ, plays the same role for equational rewriting that cong plays for setoid functions: it lets a proof replace a morphism by an equal one underneath Fโ‚. (In a setting with unique identity proofs F-resp-โ‰ˆ would be automatic; with hom-setoids it must be data, just as Func must carry cong.)

The two running examples in this library are good ones to keep in mind:

  • reductF ฯ† (Setoid.Categories.Reduct) translates the world of ๐‘†โ‚‚-algebras into the world of ๐‘†โ‚-algebras along a signature morphism ฯ†: the object map forgets (reindexes) operations, the hom map is the identity on the underlying setoid maps.
  • adjoinUnitF (Classical.Categories.AdjoinUnit) translates semigroups into monoids by freely adjoining a unit: the object map genuinely constructs (it enlarges the carrier), and the hom map extends a homomorphism to the new element.

This module also provides the identity functor idF and functor composition _โˆ˜F_. They are what make "functor" a closed vocabulary โ€” the composite of two translations is a translation โ€” and they are needed the moment a construction must name a composite functor, as the Monad record does when it types its unit Id โŸน T and multiplication T โˆ˜ T โŸน T.

{-# OPTIONS --cubical-compatible --exact-split --safe #-}

module Setoid.Categories.Functor where

open import Agda.Primitive  using ( _โŠ”_ ) renaming ( Set to Type )
open import Function           using ( id )
open import Level           using ( Level )

open import Setoid.Categories.Category using ( Category )

private variable
  o โ„“ e oโ€ฒ โ„“โ€ฒ eโ€ฒ oโ€ณ โ„“โ€ณ eโ€ณ : Level
record Functor (๐‚ : Category o โ„“ e) (๐ƒ : Category oโ€ฒ โ„“โ€ฒ eโ€ฒ) : Type (o โŠ” โ„“ โŠ” e โŠ” oโ€ฒ โŠ” โ„“โ€ฒ โŠ” eโ€ฒ) where
  open Category ๐‚ renaming (Obj to ๐‚โ‚€; Hom to ๐‚[_,_]; _โ‰ˆ_ to _โ‰ˆแตˆแต’แต_; id to idแตˆแต’แต; _โˆ˜_ to _โˆ˜แตˆแต’แต_)
  open Category ๐ƒ renaming (Obj to ๐ƒโ‚€; Hom to ๐ƒ[_,_]; _โ‰ˆ_ to _โ‰ˆแถœแต’แตˆ_; id to idแถœแต’แตˆ; _โˆ˜_ to _โˆ˜แถœแต’แตˆ_)
  field
    Fโ‚€ : ๐‚โ‚€ โ†’ ๐ƒโ‚€
    Fโ‚ : {A B : ๐‚โ‚€} โ†’ ๐‚[ A , B ] โ†’ ๐ƒ[ Fโ‚€ A , Fโ‚€ B ]
    F-resp-โ‰ˆ : {A B : ๐‚โ‚€} {f g : ๐‚[ A , B ]} โ†’ f โ‰ˆแตˆแต’แต g โ†’ Fโ‚ f โ‰ˆแถœแต’แตˆ Fโ‚ g
    identity : {A : ๐‚โ‚€} โ†’ Fโ‚ (idแตˆแต’แต {A}) โ‰ˆแถœแต’แตˆ idแถœแต’แตˆ
    homomorphism : {A B E : ๐‚โ‚€} {f : ๐‚[ A , B ] } {g : ๐‚[ B , E ]} โ†’ Fโ‚ (g โˆ˜แตˆแต’แต f) โ‰ˆแถœแต’แตˆ Fโ‚ g โˆ˜แถœแต’แตˆ Fโ‚ f

The identity functor and composition of functors

The identity functor leaves objects and morphisms untouched; its laws are each hom-setoid's reflexivity.

idF : {๐‚ : Category o โ„“ e} โ†’ Functor ๐‚ ๐‚
idF {๐‚ = ๐‚} = record  { Fโ‚€            = id
                      ; Fโ‚            = id
                      ; F-resp-โ‰ˆ      = id
                      ; identity      = โ‰ˆ-refl
                      ; homomorphism  = โ‰ˆ-refl
                      }
  where open Category ๐‚ using ( โ‰ˆ-refl )

Functors compose in the application order of their object maps: (G โˆ˜F F) first applies F, then G, on objects and morphisms alike. Each composite law unfolds to "push the inner functor's law through the outer functor, then apply the outer functor's law" โ€” one F-resp-โ‰ˆ followed by one โ‰ˆ-trans, a pattern worth noticing because every composite-functor proof in this library has this shape.

infixr 9 _โˆ˜F_

_โˆ˜F_ : {๐‚ : Category o โ„“ e} {๐ƒ : Category oโ€ฒ โ„“โ€ฒ eโ€ฒ} {๐„ : Category oโ€ณ โ„“โ€ณ eโ€ณ}
  โ†’ Functor ๐ƒ ๐„ โ†’ Functor ๐‚ ๐ƒ โ†’ Functor ๐‚ ๐„
_โˆ˜F_ {๐„ = ๐„} G F = record
  { Fโ‚€            = ฮป A โ†’ G.Fโ‚€ (F.Fโ‚€ A)
  ; Fโ‚            = ฮป f โ†’ G.Fโ‚ (F.Fโ‚ f)
  ; F-resp-โ‰ˆ      = ฮป fโ‰ˆg โ†’ G.F-resp-โ‰ˆ (F.F-resp-โ‰ˆ fโ‰ˆg)
  ; identity      = โ‰ˆ-trans (G.F-resp-โ‰ˆ F.identity) G.identity
  ; homomorphism  = โ‰ˆ-trans (G.F-resp-โ‰ˆ F.homomorphism) G.homomorphism
  }
  where
  open Category ๐„ using ( โ‰ˆ-trans )
  module F = Functor F
  module G = Functor G