In this module we'll formally prove that "a monoid is a category of one object". We do this by proving the correspondence both ways.
In the forward direction we have a module Monoid⇒Category,
parameterised on a monoid, that provides a function toCategory.
In the reverse direction we have a module Category⇒Monoid,
parameterised on a category, that provides a function toMonoid
First, we'll start with the preamble.
open import Relation.Binary using (Rel; Setoid; IsEquivalence)
module AMonoidIsACategoryOfOneObject {a ℓ} {A : Set a} where
open import Level using (0ℓ; _⊔_) renaming (suc to lsuc)
open import Data.Unit.Polymorphic using (⊤; tt)
open import Algebra.Structures {a} {ℓ}
open import Algebra.Definitions {a} {ℓ}
open import Categorical.Raw hiding (⊤)
open import Categorical.Equiv
import Categorical.Laws as Laws
open import Data.ProductWe choose the object type in the category to be ⊤. This means that
the single object is the value ‵tt`.
The morphisms of the category will be values of type A, which are
the elements of the monoid. This is quite an odd category. The
morphisms are normally thought of as something like a function, but in
this case they are just values of type A.
We define the morphism arrow as follows:
_⇨_ : ⊤ {ℓ} → ⊤ → Set a
tt ⇨ tt = ANext we provide a convenient package of a Category, Equivalent and
Laws.Category value. We use a dependent product to satisfy the
dependencies of the later values on the previous values.
CategoryAndLaws : Set (a ⊔ lsuc ℓ)
CategoryAndLaws = Σ (Category {obj = ⊤} _⇨_)
(λ cat → Σ (Equivalent ℓ {obj = ⊤} _⇨_)
(λ equiv → Laws.Category {obj = ⊤} _⇨_ ⦃ equiv ⦄ ⦃ cat ⦄))Now we are able to define the Monoid⇨Category module.
module Monoid⇒Category {_≈_ : Rel A ℓ} {_∙_ : A → A → A} {ε : A} (is-monoid : IsMonoid _≈_ _∙_ ε) where
open IsMonoid ⦃ … ⦄ public
instance
_ : IsMonoid _≈_ _∙_ ε
_ = is-monoid
open import Relation.Binary.Reasoning.Setoid {a} {ℓ} (setoid _≈_)
toCategory : CategoryAndLaws
toCategory = category , equivalent , categoryLaws
where
category : Category _⇨_
category = record { id = ε ; _∘_ = _∙_ }
equivalent : Equivalent ℓ _⇨_
equivalent = record { _≈_ = _≈_ ; equiv = isEquivalence _≈_}
categoryLaws : Laws.Category {obj = ⊤} _⇨_ ⦃ equivalent ⦄ ⦃ category ⦄
categoryLaws = record { identityˡ = λ {_ _ x} → identityˡ _≈_ x
; identityʳ = λ {_ _ x} → identityʳ _≈_ x
; assoc = λ {_ _ _ _ x y z} → assoc _≈_ z y x
; ∘≈ = ∙-cong _≈_
}And the reverse direction is done as follows.
module Category⇨Monoid ((category , equivalent , categoryLaws) : CategoryAndLaws) where
open Laws.Category ⦃ … ⦄ public
instance
_ : Category _⇨_
_ = category
_ : Equivalent ℓ _⇨_
_ = equivalent
_ : Laws.Category _⇨_
_ = categoryLaws
toMonoid : IsMonoid _≈_ _∘_ id
toMonoid =
record { isSemigroup = semigroup
; identity = (λ x → identityˡ) , (λ x → identityʳ)
}
where
magma : IsMagma _≈_ _∘_
magma = record { isEquivalence = equiv ; ∙-cong = ∘≈ }
semigroup : IsSemigroup _≈_ _∘_
semigroup = record { isMagma = magma ; assoc = λ z y x → assoc }These two modules formally prove that a monoid really is a category of one object. Given one of these entities you can transform it into the other.