On this page:
3.1 Natural Transformation
3.1.1 Composition
3.1.1.1 Horizontal Composition
3.1.1.2 Vertical Composition
3.1.1.3 Interchange Law
3.1.2 Structure of 𝐂𝐚𝐭
3.1.2.1 Horizontal Category
3.1.2.2 Vertical Category
3.2 Comma Category
3.3 Yoneda Lemma
3.3.1 Yoneda Embedding
3.3.2 Universal Element
3.4 2-Category
3.4.1 Strict Monoidal Category
3.4.1.1 Strict Symmetric Monoidal Category
3.4.2 String Diagram
3.4.3 Equivalence
8.16.0.1

3 Natural Transformation🔗ℹ

In this chapter, we extend our exploration of category theory by introducing the concept of natural transformations. Natural transformations offer a formal framework for understanding how functors between two categories correspond and interact with each other.

Building on our foundation of categories and functors, this chapter presents natural transformations in a unique way: they are defined similarly to functors, as functions that map morphisms in the domain category to corresponding morphisms in the codomain category, with the naturality condition that certain commutative diagrams hold.

This approach highlights that functors themselves can be viewed as special natural transformations, much like objects can be viewed as special morphisms, specifically as identity morphisms.

As in the previous chapter, we’ll leverage Typed Racket to illustrate the core principles, allowing us to express these abstract mathematical concepts through practical programming constructs.

    3.1 Natural Transformation

      3.1.1 Composition

        3.1.1.1 Horizontal Composition

        3.1.1.2 Vertical Composition

        3.1.1.3 Interchange Law

      3.1.2 Structure of 𝐂𝐚𝐭

        3.1.2.1 Horizontal Category

        3.1.2.2 Vertical Category

    3.2 Comma Category

    3.3 Yoneda Lemma

      3.3.1 Yoneda Embedding

      3.3.2 Universal Element

    3.4 2-Category

      3.4.1 Strict Monoidal Category

        3.4.1.1 Strict Symmetric Monoidal Category

      3.4.2 String Diagram

      3.4.3 Equivalence

3.1 Natural Transformation🔗ℹ

In a sense, α(f) can be considered the commutative square.

A natural transformation α between parallel functors F and G from 𝒞 to 𝒟, denoted by α : F G : 𝒞 → 𝒟, maps each morphism f : a → b : 𝒞 to a corresponding morphism α(f) : F(a) → G(b) : 𝒟. This mapping must adhere to the naturality condition, expressed as α(f) = α(b)∘F(f) = G(f)∘α(a), ensuring that the following diagram is commutative:

[picture] N-0.svg

The morphism α(a) in 𝒟 for an object a in 𝒞 is the component of α at a.

For a natural transformation α, there is an opposite natural transformation αop : Gop ⇒ Fop : 𝒞op → 𝒟op such that the following diagram is commutative:

[picture] N-1.svg

Exercise: For a morphism i : b → a : 𝒞. Prove that Hom𝒞(i, -) is a hom natural transformation from Hom𝒞(a, -) to Hom𝒞(b, -).

[picture] Hom_1.svg

(: 𝒞 𝐂𝐚𝐭) (: b 𝒞) (: a 𝒞) (: i (→𝒞 b a))
(: |(→𝒞 i _)| ( ([x : 𝒞] [y : 𝒞]) ( (→𝒞 x y) ( (→𝒞 a x) (→𝒞 b y)))))
(define (|(→𝒞 i _)| j)
  (define |(→𝒞 i j)| (λ (f) (∘𝒞 j f i)))
  |(→𝒞 i j)|)

Exercise: For a morphism j : x → y : 𝒞. Prove that Hom𝒞(-, j) is a hom natural transformation from Hom𝒞(-, x) to Hom𝒞(-, y).

[picture] Hom_2.svg

(: 𝒞 𝐂𝐚𝐭) (: x 𝒞) (: y 𝒞) (: j (→𝒞 x y))
(: |(→𝒞 _ j)| ( ([a : 𝒞] [b : 𝒞]) ( (→𝒞 b a) ( (→𝒞 a x) (→𝒞 b y)))))
(define (|(→𝒞 _ j)| i)
  (define |(→𝒞 i j)| (λ (f) (∘𝒞 j f i)))
  |(→𝒞 i j)|)

To verify the properties of natural transformations, we define some check procedures to automate the testing of the naturality a natural transformation has:

"code/natural_transformation/check.rkt"

#lang racket/base
 
(require rackunit)
(provide (all-defined-out))
 
(define (check-ntf 𝒞 𝒟)
  (define-values (dom𝒞 cod𝒞 ∘𝒞 ?𝒞 =𝒞) (𝒞))
  (define-values (dom𝒟 cod𝒟 ∘𝒟 ?𝒟 =𝒟) (𝒟))
  (λ (F G)
    (λ (α)
      (λ (a b f)
        (check-pred ?𝒞 a) (check-pred ?𝒟 (α a))
        (check-pred ?𝒞 b) (check-pred ?𝒟 (α b))
        (check-pred ?𝒞 f) (check-pred ?𝒟 (α f))
 
        ;; Naturality condition
        (check-true (=𝒟 (dom𝒟 (α f)) (dom𝒟 (F f)) (F a)))
        (check-true (=𝒟 (cod𝒟 (α f)) (cod𝒟 (G f)) (G b)))
        (check-true (=𝒟 (α f) (∘𝒟 (α b) (F f)) (∘𝒟 (G f) (α a))))))))
 

The following example illustrates how to implement natural transformations in Racket:

"code/natural_transformation/Set=>Rel.rkt"

#lang typed/racket/base/no-check
 
(require "../category/Set.rkt"
         "../category/Rel.rkt"
         racket/promise)
 
(: 𝒮 𝐂𝐚𝐭)
(: dom𝒮 ( ([a : 𝒮] [b : 𝒮]) ( (→𝒮 a b) a)))
(: cod𝒮 ( ([a : 𝒮] [b : 𝒮]) ( (→𝒮 a b) b)))
(: ∘𝒮 ( ([a : 𝒮] [b : 𝒮] [c : 𝒮] ... [z : 𝒮]) ( (× (→𝒮 a b) (→𝒮 b c) ...) (→𝒮 a z))))
(: ?𝒮 (pred ( ([a : 𝒮] [b : 𝒮]) (→𝒮 a b))))
(: =𝒮 ( ([a : 𝒮] [b : 𝒮] [c : 𝒮] [d : 𝒮] ...) ( (× (→𝒮 a b) (→𝒮 c d) ...) Boolean)))
(define (𝒮 m) m)
(define-values (dom𝒮 cod𝒮 ∘𝒮 ?𝒮 =𝒮) (𝐒𝐞𝐭))
 
(:  𝐂𝐚𝐭)
(: domℛ ( ([a : ] [b : ]) ( (→ℛ a b) a)))
(: codℛ ( ([a : ] [b : ]) ( (→ℛ a b) b)))
(: ∘ℛ ( ([a : ] [b : ] [c : ] ... [z : ]) ( (× (→ℛ a b) (→ℛ b c) ...) (→ℛ a z))))
(: ?ℛ (pred ( ([a : ] [b : ]) (→ℛ a b))))
(: =ℛ ( ([a : ] [b : ] [c : ] [d : ] ...) ( (× (→ℛ a b) (→ℛ c d) ...) Boolean)))
(define ( m) m)
(define-values (domℛ codℛ ∘ℛ ?ℛ =ℛ) (𝐑𝐞𝐥))
 
;; Functors from 𝒮 to 
(: F ( ([a : 𝒮] [b : 𝒮]) ( (→𝒮 a b) (→ℛ (F a) (F b)))))
(define F
  (let ()
    (define (F.map m) (for/set ([(x y) (in-hash m)]) (cons x y)))
    (λ (f)
      (define a (dom𝒮 f))
      (define b (cod𝒮 f))
      (define a.map (function-map a))
      (define b.map (function-map b))
      (define f.map (function-map f))
      (define Fa (relation (lazy Fa) (lazy Fa) (F.map a.map)))
      (define Fb (relation (lazy Fb) (lazy Fb) (F.map b.map)))
      (define Ff (relation (lazy Fa) (lazy Fb) (F.map f.map)))
      Ff)))
 
(: G ( ([a : 𝒮] [b : 𝒮]) ( (→𝒮 a b) (→ℛ (G a) (G b)))))
(define G
  (let ()
    (define (G.map m) (for/set ([(x y) (in-hash m)]) (cons (list x) (list y))))
    (λ (f)
      (define a (dom𝒮 f))
      (define b (cod𝒮 f))
      (define a.map (function-map a))
      (define b.map (function-map b))
      (define f.map (function-map f))
      (define Ga (relation (lazy Ga) (lazy Ga) (G.map a.map)))
      (define Gb (relation (lazy Gb) (lazy Gb) (G.map b.map)))
      (define Gf (relation (lazy Ga) (lazy Gb) (G.map f.map)))
      Gf)))
 
;; Natural Transformations from F to G
(: α ( ([a : 𝒮] [b : 𝒮]) ( (→𝒮 a b) (→ℛ (F a) (G b)))))
(define α
  (let ()
    (define (F.map m) (for/set ([(x y) (in-hash m)]) (cons       x        y)))
    (define (G.map m) (for/set ([(x y) (in-hash m)]) (cons (list x) (list y))))
    (define (α.map m) (for/set ([(x y) (in-hash m)]) (cons       x  (list y))))
    (λ (f)
      (define a (dom𝒮 f))
      (define b (cod𝒮 f))
      (define a.map (function-map a))
      (define b.map (function-map b))
      (define f.map (function-map f))
      (define Fa (relation (lazy Fa) (lazy Fa) (F.map a.map)))
      (define Gb (relation (lazy Gb) (lazy Gb) (G.map b.map)))
      (define αf (relation (lazy Fa) (lazy Gb) (α.map f.map)))
      αf)))
 
(module+ test
  (require "check.rkt")
 
  ;; Objects in 𝒮
  (: a 𝒮) (define a (function (lazy a) (lazy a) #hash([x0 . x0] [x1 . x1])))
  (: b 𝒮) (define b (function (lazy b) (lazy b) #hash([y0 . y0] [y1 . y1])))
 
  ;; Morphisms in 𝒮
  (: f (→𝒮 a b)) (define f (function (lazy a) (lazy b) #hash([x0 . y0] [x1 . y0])))
 
  (define check-𝐒𝐞𝐭⇒𝐑𝐞𝐥 (check-ntf 𝐒𝐞𝐭 𝐑𝐞𝐥))
  (define check-F⇒G (check-𝐒𝐞𝐭⇒𝐑𝐞𝐥 F G))
  (define check-α (check-F⇒G α))
  (check-α a b f))
 
3.1.1 Composition🔗ℹ

In this section, we explore two types of composition for natural transformations: horizontal composition and vertical composition. These forms of composition are fundamental to understanding how natural transformations interact and provide a deeper insight into their algebraic properties.

3.1.1.1 Horizontal Composition🔗ℹ

Given that natural transformations are defined as mappings of morphisms, it is natural to consider whether and how they can be composed, similar to the composition of functors. In fact, a key insight is that functors themselves can be viewed as special types of natural transformations. This leads us to define a type of composition for natural transformations, known as horizontal composition.

Consider two natural transformations α : F ⇒ G : 𝒞 → 𝒟 and β : H ⇒ K : 𝒟 → ℰ. The horizontal composition β∘α : H∘F ⇒ K∘G : 𝒞 → ℰ is a new natural transformation that, for each morphism f : a → b : 𝒞, maps it to β∘α(f) = β(α(f)) : H∘F(a) → K∘G(b) : ℰ.

Exercise: Prove α = α∘id𝒞 = id𝒟∘α.

Exercise: Show the types of H∘α, K∘α, β∘F, and β∘G.

We often omit the composition symbol when dealing with functors and natural transformations. For instance, β∘α(f) are typically simplified to βα(f) or βαf. This simplification makes it easier to reason about complex structures involving multiple functors and natural transformations, reducing visual clutter and improving readability.

[picture] N-2.svg

Exercise: Prove that the horizontal composition of natural transformations ensures that the resulting diagram is commutative.

For βα, its type is HF ⇒ KG, where HF and KG are functors from 𝒞 to . Additionally, there are three important commutative squares associated with βα:

  1. βα(f) : HF(f) ⇒ KG(f) [picture] N-2_1.svg

  2. βα(f) : Hα(f) ⇒ Kα(f) [picture] N-2_2.svg

  3. βα(f) : βF(f) ⇒ βG(f) [picture] N-2_3.svg

Note that , , βF, and βG are all natural transformations, not functors. These three commutative squares arise naturally because βα(f) is the body diagonal of a commutative cube, and there are precisely three faces of this cube whose face diagonals coincide with this body diagonal. Each of these faces also has a cube edge that starts from HF(a), which uniquely identifies them among all the cube’s faces:

[picture] N-2_4.svg

Exercise: Prove that horizontal composition is associative.

3.1.1.2 Vertical Composition🔗ℹ

Since two adjacent commutative squares can themselves be composed to form a larger commutative square, it naturally suggests that two natural transformations that share a common functor can also be composed to form a new natural transformation. This leads us to define a type of composition for natural transformations, known as vertical composition.

Consider two natural transformations α : F ⇒ G : 𝒞 → 𝒟 and β : G ⇒ H : 𝒞 → 𝒟. The vertical composition β∙α : F ⇒ H : 𝒞 → 𝒟 is a new natural transformation that, for each morphism f : a → b : 𝒞, maps it to β∙α(f) : F(a) → H(b) : 𝒟.

Exercise: Prove α = α∙F = G∙α.

[picture] N-3.svg [picture] N-3_1.svg [picture] N-3_2.svg

Exercise: Prove that the vertical composition of natural transformations ensures that the resulting diagram is commutative.

Exercise: Prove that vertical composition is associative.

3.1.1.3 Interchange Law🔗ℹ

The Interchange Law explains how horizontal composition and vertical composition of natural transformations interact with each other.

To understand how the IL works, recall that applying a natural transformation to a morphism often results in a morphism which is the diagonal of a commutative square. All composition of natural transformations with the same domain and codomain ultimately produce the same commutative squares, so that they are equal. This is precisely what the IL states.

Consider the natural transformations α0 : F ⇒ G : 𝒞 → 𝒟, β0 : G ⇒ H : 𝒞 → 𝒟, α1 : K ⇒ L : 𝒟 → ℰ, and β1 : L ⇒ M : 𝒟 → ℰ. The commutative diagram below illustrates the relationships between them:

[picture] N-4.svg

In some category theory texts, denotes vertical composition and denotes horizontal composition: (β1∗β0)(α1∗α0) = (β1∘α1)(β0∘α0).

We can vertically compose α0 with β0, and α1 with β1, as well as horizontally compose α0 with α1, and β0 with β1. The IL states that the horizontal composition of two vertical compositions is equal to the vertical composition of two horizontal compositions. More precisely, the interchange law (IL) can be written as: (β1∘β0)(α1∘α0) = (β1∙α1)(β0∙α0).

[picture] IL.svg

Here are some important commutative squares that arise:

  1. (β1∘β0)(α1∘α0)(f) : KF(f) ⇒ MH(f) [picture] N-4_0.svg

  2. (β1∙α1)(β0∙α0)(f) : KF(f) ⇒ MH(f) [picture] N-4_1.svg

  3. (β1∙α1)(β0∙α0)(f) : K(β0∙α0)(f) ⇒ M(β0∙α0)(f) [picture] N-4_2.svg

  4. (β1∙α1)(β0∙α0)(f) : (β1∙α1)F(f)(β1∙α1)H(f) [picture] N-4_3.svg

[picture] N-4_4.svg

3.1.2 Structure of 𝐂𝐚𝐭🔗ℹ

In the previous chapter, we introduced what we referred to as 𝐂𝐚𝐭, which consists of categories as objects and functors as morphisms. Strictly speaking, this was actually the base category of 𝐂𝐚𝐭, denoted by 𝐂𝐚𝐭b.

[picture] Cat^b.svg

With the introduction of natural transformations, we can now see that functors are actually a special case of natural transformations. This observation reveals that the full structure of 𝐂𝐚𝐭 is richer and more complex compared to other categories, as it includes natural transformations in addition to functors.

The complete 𝐂𝐚𝐭 can be understood as being composed of two additional interrelated categories: the horizontal category and the vertical category. These categories give us deeper insights into the complex structure of 𝐂𝐚𝐭 and how the different components (categories, functors, and natural transformations) interact with each other.

3.1.2.1 Horizontal Category🔗ℹ

The horizontal category of 𝐂𝐚𝐭, denoted by 𝐂𝐚𝐭h, can be viewed as an extension of 𝐂𝐚𝐭b. In 𝐂𝐚𝐭b, objects are categories and morphisms are functors between categories. In 𝐂𝐚𝐭h, the objects remain the same but the morphisms are generalized to include all natural transformations between functors.

[picture] Cat^h.svg

In 𝐂𝐚𝐭h, horizontal composition serves as the composition operation for morphisms in it. This perspective allows us to see that horizontal composition essentially works like the composition of functions: both functors and natural transformations are kinds of functions between categories.

3.1.2.2 Vertical Category🔗ℹ

The vertical category of 𝐂𝐚𝐭, denoted by 𝐂𝐚𝐭v, provides a perspective that focuses on the relationships between functors through natural transformations. In 𝐂𝐚𝐭v, objects are functors between categories and morphisms are natural transformations between functors. An isomorphism α : F ⇒ G in 𝐂𝐚𝐭v is called a natural isomorphism, and F and G are naturally isomorphic to each other.

[picture] Cat^v.svg

Exercise: Prove that a natural transformation α : F ⇒ G : 𝒞 → 𝒟 is a natural isomorphism iff each component of α is an isomorphism in 𝒟.

Exercise: For a natural isomorphism α : F ⇒ G : 𝒞 → 𝒟 and a morphism f : a → b : 𝒞. Prove F(f) = α1(b)∘G(f)∘α(a) and G(f) = α(b)∘F(f)∘α1(a).

In 𝐂𝐚𝐭v, vertical composition serves as the composition operation for morphisms in it. This perspective helps us understand why functors can be viewed as a special case of natural transformations.

Consider a functor category [𝒞 → 𝒟] (exponential category 𝒟𝒞), which has all the functors from 𝒞 to 𝒟 as objects, and all the natural transformations between those functors as morphisms. In this category, every functor F : 𝒞 → 𝒟 can be viewed as the identity natural transformation idF : F ⇒ F, which acts as the identity morphism.

Exercise: For objects 𝒜, , and 𝒞 in 𝐂𝐚𝐭. Prove the exponential laws:

Exercise: Think about what structure an endofunctor category [𝒞 → 𝒞] exhibits when considering horizontal composition.

In Racket, to distinguish between operations in the horizontal category and vertical category, we introduce the notions of src, tgt, and to denote the domain, codomain, and compose operators in 𝒟𝒞. Additionally, we stipulate that () and () must return the same value.

Exercise: Try to define make-vertical-compose so that we can define the compose operator in 𝒟𝒞 like this:

(define  (make-vertical-compose 𝒞 𝒟))

3.2 Comma Category🔗ℹ

In previous content, we examined how natural transformations provide a framework for studying relationships between two functors with the same domain and codomain. Now, we consider a more general question: can we use a similar structure to investigate functors with different domains but the same codomain?

As a function that maps morphisms, a natural transformation α : F ⇒ G : 𝒞 → 𝒟 establishes a relationship between F and G through the naturality condition. Specifically, for each morphism f in 𝒞, α(f) corresponds uniquely to a commutative square. In this sense, studying the relationship between F and G via α essentially constructs an arrow category, where objects are the components of α, and morphisms are the commutative squares that satisfy the naturality condition.

Inspired by this approach, we can investigate the relationship between two functors F: 𝒞 → ℰ and G: 𝒟 → ℰ by constructing an arrow category that represents the interactions between F and G. In such a category, objects are triples (a, x, α), where a is an object in 𝒞, x is an object in 𝒟, and α : F(a) → G(x) is a morphism in . The morphisms in this category are pairs (i, j), where i : a → b is a morphism in 𝒞 and j : x → y is a morphism in 𝒟, such that the following diagram is commutative:

[picture] comma_1.svg

This category is called a comma category of F and G, denoted by F/G (F↓G).

Exercise: Try using comma category to define arrow category and (co)slice category.

To explore the relationships between F/G, 𝒞, 𝒟, and , we introduce two forgetful functors HF : F/G → 𝒞 and HG : F/G → 𝒟. HF maps (a, x, α) to a and (i, j) to i, while HG maps (a, x, α) to x and (i, j) to j. Furthermore, these functors are connected by a natural transformation θ : F∘HF ⇒ G∘HG, which maps (a, x, α) to α.

[picture] comma_2.svg

Building on the earlier motivation, we saw that comma categories can be used to study relationships between two functors with the same codomain. Since natural transformations describe relationships between functors with the same domain and codomain, it is natural to explore their connection with comma categories.

Given a natural transformation α : F ⇒ G : 𝒞 → 𝒟, we can construct a functor A : 𝒞 → F/G such that HF∘A = HG∘A = id𝒞. Conversely, given such a functor A, we can construct a natural transformation α.

[picture] ntf-as-ftr.svg

3.3 Yoneda Lemma🔗ℹ

Philosophically speaking, one might say that the essence of an entity lies in the totality of its relationships with other entities. In category theory, this idea extends to morphisms, which can be seen as fundamental "entities" within a category.

We can express this concept by examining the relationships between a morphism f : a → x in a category 𝒞 and other morphisms in 𝒞. Specifically, we use the natural transformations Hom𝒞(f, -) : Hom𝒞(x, -) ⇒ Hom𝒞(a, -) : 𝒞 → 𝐒𝐞𝐭 and Hom𝒞(-, f) : Hom𝒞(-, a) ⇒ Hom𝒞(-, x) : 𝒞op → 𝐒𝐞𝐭 to describe how f interacts with other morphisms in 𝒞.

This naturally leads us to ask about the connection between f, Hom𝒞(f, -), and Hom𝒞(-, f). The Yoneda Lemma, a cornerstone of category theory, addresses this question by establishing that these perspectives are in one-to-one correspondence with each other.

The Yoneda Lemma sets up a one-to-one correspondence between elements of F(S), where S : 𝒞 and F : 𝒞 → 𝐒𝐞𝐭, and variable elements of F, parametrized by Hom𝒞(S, -). Specifically, an element s ∈ F(S) uniquely corresponds to a natural transformation ρ : Hom𝒞(S, -) ⇒ F.

[picture] run_1.svg

To better understand the Yoneda Lemma, let’s revisit the TDFA defined in Typed Deterministic Finite Automaton. We denote the free category of the typed alphabet 𝒢 as 𝒞, and let F : 𝒞 → 𝐒𝐞𝐭 represent the typed action φ*. In this context, consider the run function, which takes an input sequence w and returns a final state F(w)(s0) after processing w, starting from the start state s0.

According to the Yoneda Lemma, we see that each component of a natural transformation ρ : Hom𝒞(S, -) ⇒ F at an object T : 𝒞 can be understood as a run function starting from a state s ∈ F(S): ∀w ∈ Hom𝒞(S, T), ρ(T)(w) = F(w)(s). Here, F(T) can be interpreted as the set of final states.

To illustrate this correspondence, we use Racket code to define two procedures: s->ρ and ρ->s. They demonstrate how an element s of F(S) can be transformed into a natural transformation ρ, and vice versa, providing a concrete way to visualize the one-to-one correspondence described by the Yoneda Lemma.

"code/natural_transformation/s<->run.rkt"

#lang typed/racket/base/no-check
 
(require "../../exercises/functor/make-path.rkt"
         (only-in "../functor/TDFA.rkt" 𝒢 [F𝒢 𝒞]))
(require/typed "../functor/TDFA.rkt"
  [(φ* F) ( ([X : 𝒞] [Y : 𝒞]) ( (→𝒞 X Y) ( (F X) (F Y))))])
 
(module+ test (require rackunit))
 
(define-values (dom𝒞 cod𝒞 ∘𝒞 ?𝒞 =𝒞) (𝒞))
 
(: S 𝒞) (define S (make-path 𝒢 'S0 ""))
 
(: |(→𝒞 S _)| ( ([X : 𝒞] [Y : 𝒞]) ( (→𝒞 X Y) ( (→𝒞 S X) (→𝒞 S Y)))))
(define (|(→𝒞 S _)| j)
  (define |(→𝒞 S j)| (λ (f) (∘𝒞 j f)))
  |(→𝒞 S j)|)
 
(: s->ρ ( (F S) ( |(→𝒞 S _)| F)))
(define (s->ρ s)
  (: ρ ( ([X : 𝒞] [Y : 𝒞]) ( (→𝒞 X Y) ( (→𝒞 S X) (F Y)))))
  (define (ρ j) (λ (f) ((F (∘𝒞 j f)) s)))
  ρ)
 
(: ρ->s ( ( |(→𝒞 S _)| F) (F S)))
(define (ρ->s ρ)
  (define s ((ρ S) S))
  s)
 
(module+ test
  (for ([s (in-list '(s0 a0 r0))])
    (define ρ (s->ρ s))
    (check-eq? s (ρ->s ρ))
    (for ([w (in-list (list (make-path 𝒢 'S0 "1xyxyxx")))])
      (define T (cod𝒞 w))
      (check-eq? ((ρ T) w) ((F w) s)))))
 

This correspondence also holds for contravariant hom functors. There is a one-to-one correspondence between elements of G(T), where T : 𝒞op and G : 𝒞op → 𝐒𝐞𝐭, and variable elements of G, parametrized by Hom𝒞(-, T). Specifically, an element t ∈ G(T) uniquely corresponds to a natural transformation ρ : Hom𝒞(-, T) ⇒ G.

[picture] run_2.svg

Exercise: Try to define two procedures using Racket code: t->ρ and ρ->t.

Forgetful functors to 𝐒𝐞𝐭 are very often representable.

The definition of the Yoneda Lemma can be generalized by replacing the hom functor Hom𝒞(S, -) with any functor that is naturally isomorphic to it. Such a functor is called a representable functor and we say that S represents this functor.

Exercise: For a functor F : 𝒞 → 𝐒𝐞𝐭. Prove that if objects a and x in 𝒞 both represent F, then a ≅ x.

3.3.1 Yoneda Embedding🔗ℹ

The Yoneda Lemma establishes a powerful correspondence: a natural transformation ρ : Hom𝒞(S, -) ⇒ F uniquely corresponds to an element s ∈ F(S). By carefully selecting functor F, we can choose to study specific entities within the corresponding set F(S) and examine the relationship between these entities and natural transformations.

For example, if we let F be a hom functor, then the elements of F(S) are precisely the morphisms in 𝒞 that start from or end to S. An important corollary of the Yoneda Lemma is that any natural transformation between hom functors in a category 𝒞 must be a hom natural transformation because it corresponds exactly to a morphism in 𝒞.

To illustrate this, consider two hom functors Hom𝒞(x, −) and Hom𝒞(a, −), where a and x are objects in 𝒞. According to the Yoneda Lemma, an element f ∈ Hom𝒞(a, x), which is also a morphism in 𝒞, uniquely corresponds to the hom natural transformation Hom𝒞(f, -) : Hom𝒞(x, -) ⇒ Hom𝒞(a, -).

This shows that any natural transformation between hom functors is directly determined by a morphism in 𝒞. Thus, the Yoneda Lemma establishes a one-to-one correspondence between a morphism f and a hom natural transformation Hom𝒞(f, -).

Exercise: Show the one-to-one correspondence between f and Hom𝒞(-, f).

Exercise: Prove that f is an isomorphism in 𝒞 iff Hom𝒞(f, -) is a natural isomorphism, and iff Hom𝒞(-, f) is a natural isomorphism.

Building on the correspondence established by the Yoneda Lemma, we can define a functor Y : 𝒞op[𝒞 → 𝐒𝐞𝐭] that maps each object a : 𝒞 to the covariant hom functor Hom𝒞(a, -), and each morphism i : b → a : 𝒞 to the hom natural transformation Hom𝒞(i, -) : Hom𝒞(a, -) ⇒ Hom𝒞(b, -). This functor is known as the Yoneda embedding for 𝒞.

(: Y ( ([a : 𝒞] [b : 𝒞]) ( (→𝒞 b a) ( ([x : 𝒞] [y : 𝒞]) ( (→𝒞 x y) ( (→𝒞 a x) (→𝒞 b y)))))))
(define Y (curry |(→𝒞 _ _)|))

Exercise: Prove that Y is an embedding.

Here is another Yoneda embedding J : 𝒞 → [𝒞op → 𝐒𝐞𝐭] that maps each object x : 𝒞 to the contravariant hom functor Hom𝒞(-, x), and each morphism j : x → y : 𝒞 to the hom natural transformation Hom𝒞(-, j) : Hom𝒞(-, x) ⇒ Hom𝒞(-, y).

(: J ( ([x : 𝒞] [y : 𝒞]) ( (→𝒞 x y) ( ([a : 𝒞] [b : 𝒞]) ( (→𝒞 b a) ( (→𝒞 a x) (→𝒞 b y)))))))
(define J (curryr |(→𝒞 _ _)|))

Exercise: Prove that J is an embedding.

In Cayley’s Theorem, we explored the categorical version of Cayley’s theorem, which provides a way to represent an object b : 𝒞 via the functor H, such that H(b) = ∐a∈𝒞0Hom𝒞(a, b).

Building on this idea, the Yoneda embedding generalizes Cayley’s theorem. The functor J represents an object b : 𝒞 as a hom functor, such that J(b) = Hom𝒞(-, b). Moreover, any representable functors naturally isomorphic to Hom𝒞(-, b) can also be used to represent b.

The Yoneda embedding has interesting connections to programming paradigms, such as Continuation-Passing Style (CPS). Specifically, when applied to 𝐒𝐞𝐭, the Yoneda embedding J maps a set x to the endofunctor Hom𝐒𝐞𝐭(-, x), which encapsulates computations that use functions as continuations to produce results in x.

To illustrate this, consider a result type x. In Typed Racket, the type of J(x) can be expressed as: ( (a b) ( ( b a) ( ( a x) ( b x)))). By uncurrying it, we obtain a procedure cps:

(: cps ( (a b) ( ( b a) ( b ( a x) x))))
(define (cps i) (λ (m k) (k (i m))))

This type signature shows that cps maps a procedure i of type ( b a) to a procedure cps(i) of type ( b ( a x) x). In other words, instead of returning a result of type a directly like i, cps(i) requires an additional argument to indicate the continuation of type ( a x) that specifies what to do with the result once it is produced. In many programming languages, the keyword return serves as a form of continuation, directing where to proceed after a result is obtained.

3.3.2 Universal Element🔗ℹ

In our earlier discussion of the Yoneda Lemma, we highlighted how category theory views a morphism in terms of its relationships with other morphisms. This was illustrated by the one-to-one correspondence between f, Hom𝒞(f, -), and Hom𝒞(-, f).

The Yoneda Lemma showed that this correspondence holds when we substitute F for a hom functor. But what if F is a more general representable functor? This naturally leads to the question: What special property does the elements corresponding to the natural isomorphisms have in such cases? The answer is the universal property, which is reflected by the concept of universal elements.

A universal element of a functor F : 𝒞 → 𝐒𝐞𝐭 is an element s ∈ F(S) for some object S : 𝒞 such that, for any other object T : 𝒞 and element t ∈ F(T), there exists a unique morphism w : S → T : 𝒞 for which t = F(w)(s). This reflects the general form of a universal property, which is typically described as follows: ∀T ∈ 𝒞0, ∃!w ∈ Hom𝒞(S, T), t = F(w)(s).

Exercise: Prove that an object S : 𝒞 represents a functor F : 𝒞 → 𝐒𝐞𝐭 iff there exists a universal element s ∈ F(S).

Exercise: Prove that s is a universal element of F iff the natural transformation ρ : Hom𝒞(S, -) ⇒ F corresponding to s is a natural isomorphism, i.e., each component of ρ at an object T : 𝒞 is a bijection: ρ(T)1(t) = w.

Exercise: Prove that if s ∈ F(S) and t ∈ F(T) both are universal elements of F, then there is a unique isomorphism between S and T in 𝒞.

The concept of universal elements mirrors the universal property seen in initial objects, where there exists a unique morphism f from an initial object 0 to any other object a in the same category 𝒞: ∀a ∈ 𝒞0, ∃!f ∈ 𝒞1, dom𝒞(f) = 0 ∧ cod𝒞(f) = a.

In fact, any universal property can be viewed as an instance of an initial object in some category (usually the comma category). For example, universal elements of a representable functor F : 𝒞 → 𝐒𝐞𝐭 can be seen as initial objects in T:𝒞F(T).

Exercise: Prove that F is a representable functor iff there exists an initial object in 𝒞F.

Exercise: Prove that the state diagram of a TDFA is a tree whose root is the start state s0 iff s0 is a universal element of the typed action.

Exercise: For a category 𝒞 and an object a : 𝒞. Prove x:𝒞Hom𝒞(a, x) ≅ a/𝒞.

3.4 2-Category🔗ℹ

A set (0-category) is defined by a collection of elements (0-cells). Extending this idea, a category (1-category) is defined by two collections: objects (0-cells) and morphisms (1-cells). Importantly, in a category, objects can be seen as identity morphisms, a special case of morphisms.

This natural progression leads us to consider whether we can extend our abstraction to include 2-morphisms (2-cells). In other words, we can think about constructing a 2-category, which is defined by not only 0-cells and 1-cells but also 2-cells. Just as in a 1-category, each 0-cell is an identity 1-cell, in a 2-category, each 1-cell is an identity 2-cell.

We already have an example of such a structure: 𝐂𝐚𝐭. In 𝐂𝐚𝐭, categories serve as 0-cells, functors act as 1-cells, and natural transformations provide the additional layer of abstraction as 2-cells. This makes 𝐂𝐚𝐭 a natural reference for understanding the concept of 2-categories.

To formalize this idea, we look at how 𝐂𝐚𝐭 operates. There are two distinct composition operations for natural transformations within 𝐂𝐚𝐭: horizontal composition and vertical composition. The interaction between these two forms of composition follows the interchange law. We can describe 𝐂𝐚𝐭 in terms of three interrelated categories: the base category 𝐂𝐚𝐭b, the horizontal category 𝐂𝐚𝐭h, and the vertical category 𝐂𝐚𝐭v.

Note that 𝒞2 of a 1-category 𝒞 is the collection of composable pairs.

Using these properties, we define a 2-category 𝐂 as a structure consisting of three collections: 𝐂i of i-morphisms (i-cells) for i = 0, 1, 2. In 𝐂, there are two ways to compose 2-cells: horizontal composition and vertical composition, which satisfy the interchange law. Additionally, 𝐂 can be described in terms of three 1-categories:

An isomorphism α : F ⇒ G in 𝐂v is called a 2-isomorphism, and F and G are 2-isomorphic to each other.

In a general 2-category, we may not know the specific internal structure of the 1-cells. However, we can draw inspiration from the concept of global elements. In 𝐂𝐚𝐭, any category 𝒞 is isomorphic to 𝒞1. This observation motivates us to define a similar concept in any 2-category 𝐂 that contains a terminal object 1. Specifically, for any 0-cell 𝒞 : 𝐂, we define the 1-cells from 1 to 𝒞 as the global objects of 𝒞, and the 2-cells between them as the global morphisms of 𝒞.

Having introduced the concept of 2-categories, we naturally consider the mappings between 2-categories. Just as 1-functors map between 1-categories by preserving their structure, 2-functors map between 2-categories, preserving the richer structure.

To define a 2-functor, we note that a 2-category 𝐂 consists of three collections: 𝐂0, 𝐂1 and 𝐂2. Consequently, a 2-functor F : 𝐂 → 𝐃 consists of three functions: F0 : 𝐂0 → 𝐃0, F1 : 𝐂1 → 𝐃1, and F2 : 𝐂2 → 𝐃2. Additionally, F can be described in terms of three 1-functors:

3.4.1 Strict Monoidal Category🔗ℹ

A strict monoidal category (𝒞, ⊗, I) is a category 𝒞 equipped with a tensor product and a tensor unit I. The tensor product is a functor ⊗ : 𝒞×𝒞 → 𝒞, and the tensor unit is a unit object I : 𝒞, such that for all morphisms f, g, h in 𝒞, (f⊗g)⊗h = f⊗(g⊗h) and f = f⊗idI = idI⊗f.

[picture] mon-cat.svg

Exercise: Prove the interchange law: (g0⊗g1)(f0⊗f1) = (g0∘f0)(g1∘f1).

The following is an example of a strict monoidal category:

"code/natural_transformation/Matr.rkt"

#lang typed/racket/base/no-check
 
(require math/array math/matrix)
(require "../category/Matr.rkt")
 
(provide  (all-from-out "../category/Matr.rkt"))
 
(: I (Matrix Nothing))
(define I #;(identity-matrix 0) (array #[]))
 
(:  ( ([a : ] [b : ] [x : ] [y : ]) ( (× (→ℳ a b) (→ℳ x y)) (→ℳ ( a x) ( b y)))))
(define ( . m*)
  (let ([m* (remq* (list I) m*)])
    (if (null? m*) I (block-diagonal-matrix m*))))
 
(module+ test
  (require "../category/check.rkt"
           rackunit)
  (define-values (dom cod  ? =) (𝐌𝐚𝐭𝐫))
  (define (rand m n) (random 1 9))
 
  ;; Objects
  (define a (identity-matrix 1))
  (define b (identity-matrix 2))
  (define c (identity-matrix 3))
  (define d (identity-matrix 4))
 
  ;; Morphisms
  (define f (build-matrix 2 1 rand))
  (define g (build-matrix 3 2 rand))
  (define h (build-matrix 4 3 rand))
 
  (define check-𝐌𝐚𝐭𝐫 (check-cat 𝐌𝐚𝐭𝐫))
  (check-𝐌𝐚𝐭𝐫 a b c d f g h)
 
  ;; Strict Monoidal Category
  (check-true (= f ( f ()) ( () f)))
  (check-true (= ( h g f) ( h ( g f)) ( ( h g) f)))
 
  ;; Interchange Law
  (define f0 f)
  (define f1 g)
  (define g0 g)
  (define g1 h)
  (check-true
   (= ( ( g0 g1) ( f0 f1))
      ( ( g0 f0) ( g1 f1)))))
 

If 𝒞 is a discrete category, i.e., a set, then the strict monoidal category (𝒞, ⊗, I) reduces to a monoidal set. In this case, becomes an associative binary operation and I becomes the identity element of 𝒞. This structure corresponds exactly to what we call a monoid. Hence, monoidal set and monoid are the same concept.

Just as a one-object category 𝒞 can be viewed as a monoid (𝒞1, ∘, id), we extend this idea to view a one-object 2-category 𝐂 as a strict monoidal category (𝐂v, ∘, idb). In this context, the vertical category 𝐂v is equipped with the horizontal composition , which acts as the tensor product, and the identity 1-cell idb, which serves as the tensor unit.

Exercise: Show that every endofunctor category is a strict monoidal category.

3.4.1.1 Strict Symmetric Monoidal Category🔗ℹ

A strict symmetric monoidal category (𝒞, ⊗, I) is a strict monoidal category that is symmetric: for all morphisms f, g in 𝒞, f⊗g = g⊗f.

3.4.2 String Diagram🔗ℹ

Traditional diagrams represent 0-cells as nodes, 1-cells as single arrows between these nodes, and 2-cells as double arrows between these single arrows. In contrast, string diagrams provide a more intuitive and geometrical representation:

String diagrams are a powerful tool for visualizing relationships between i-cells within a 2-category 𝐂. Below, we illustrate a 2-cell α : F ⇒ G : 𝒞 → 𝒟 : 𝐂, using both a traditional diagram and a corresponding string diagram:

By default, string diagrams are read from right to left and from bottom to top.

[picture] alpha.svg

We also use special notations in string diagrams:

The following two examples illustrate the special notations used in string diagrams. These string diagrams show equivalent but visually distinct representations of the same structures.

The first one shows a 2-cell α : G∘F ⇒ id𝒞, where F : 𝒞 → 𝒟 : 𝐂 and G : 𝒟 → 𝒞 : 𝐂:

[picture] alpha_0.svg [picture] alpha_1.svg [picture] alpha_2.svg [picture] alpha_3.svg [picture] alpha_4.svg

The second one shows two 2-cells α : G∘F ⇒ id𝒞 and β : id𝒟 ⇒ H∘G, where F : 𝒞 → 𝒟 : 𝐂, G : 𝒟 → 𝒞 : 𝐂, and H : 𝒞 → 𝒟 : 𝐂:

[picture] beta&alpha_0.svg [picture] beta&alpha_1.svg [picture] beta&alpha_2.svg [picture] beta&alpha_3.svg [picture] beta&alpha_4.svg

The advantage of using string diagrams lies in their simplicity when representing complex structures in a 2-category. Instead of working with layers of nodes and arrows, string diagrams allow us to represent these relationships in a clear, visual manner that highlights how each part of the structure interacts with the others.

Exercise: The following is a string diagram, try to draw the corresponding diagram.

[picture] str-diag.svg

If there are no 2-cells in a string diagram, we can further compress it for simplicity. Specifically:

This compressed representation is not limited to 𝐂b but can also be extended to other 1-categories.

3.4.3 Equivalence🔗ℹ

In a 2-category 𝐂, equivalence is a weaker version of isomorphism. For 1-cells F: 𝒞 → 𝒟 : 𝐂 and G: 𝒟 → 𝒞 : 𝐂, if id𝒞 ≅ G∘F and F∘G ≅ id𝒟, then F and G are both equivalences (often called be weakly invertible).

[picture] eqv_1.svg [picture] eqv_2.svg

In this case, both F and G are inverses up to 2-isomorphisms η : id𝒞 ⇒ G∘F and ϵ : F∘G ⇒ id𝒟. G is a pseudo-inverse of F, and F is a pseudo-inverse of G. 𝒞 and 𝒟 are equivalent to each other (𝒞 𝒟) if there exists an equivalence between them.

Exercise: Prove that if η and ϵ are identities, then 𝒞 ≅ 𝒟.

Exercise: Prove that is an equivalence relation over 𝐂0.

Exercise: Prove that every 0-cell is equivalent to itself.

Exercise: Prove that the pseudo-inverse of an equivalence is not unique.

Exercise: Prove that 𝐓𝐫𝐞𝐞 is equivalent to 𝐅𝐬𝐭.