A general optic can be defined as a set of bidirectional transformations:

O(s, s')(a, a') = \int^{m \colon M} C(s, m \triangleright a) \times D(m \blacktriangleright a', s')

It is buit from two actegories, C and D; each with its own monoidal action by a monoidal category M (the two actions are represented by two different triangles).

A product of two hom-sets may be interpreted as a hom-set in a product category. The reversal of one of the hom-set may be accomplished by invoking the opposite category.

If we use \underline s for a pair of objects (s, s') in C \times D^{op}, and \underline a for (a, a'), we may want to encode such an optic as:

O \underline s \; \underline a = \int^m (C \times D^{op})( \underline s, m \triangleright  \underline a)

with the action m \triangleright \underline a = (m \triangleright a, m \blacktriangleright a').

This is a slight abuse of notation. Normally, a coend variable m should occur in the integrand twice; once in a covariant and once in a contravariant position. To justify this new notation, let’s dig deeper into the definition of a coend.

A coend \int^m P (m, m) is a giant sum over all the the sets formed by taking the diagonal elements of the profunctor P — modulo certain identifications. These identifications are crucial, because they probe the structure of the categories in question; they tell us that we are overcounting certain set elements because they are reachable through underlying morphisms.

The identification is done through cowedges. A cowedge with a vertex V is a family of morphisms (injections) \iota_m \colon P (m, m) \to V such that for any morphism f \colon m \to n the following diagram commutes:

We read the commuting condition as:

\iota_m \circ P(f, m) = \iota_n \circ P(n, f)

In a sum (disjoint union) of all these sets P(m, m), we identify the elements that can be reached through such composites. One composite contains the lifting of the pair (f, id_m); and the other, the lifting of (id_n, f).

Cowedges form a category, and the terminal cowedge for a given profunctor is called the coend.

Twisted Arrow Category

A giant sum with identifications can also be described as a colimit, if we can find the appropriate category to define the cocones. We will want to match cocones with cowedges.

Each cowedge corresponds to a family of injections \iota_m and an arrow f in M. This suggests that the appropriate category for constructing the colimit is the category of arrows. An object is this category is an arrow f  \colon m \to n or, more precisely, a triple (m, n, f).

The tricky part is to define morphisms between arrows. Since we are working with profunctors, it makes sense to define a morphism between (m, n, f) and (m', n', f') as a pair of arrows going in opposite directions:

(u \colon m' \to m, v \colon n \to n')

More precisely, a morphism between arrows is a pair of morphisms (u, v) satisfying the commuting condition f' = v \circ f \circ u:

(Incidentally, without this commuting condition, all arrows between a fixed pair of objects would be isomorphic.)

Such a category is called a twisted-arrow category \mathbf{Tw}(M).

It can be shown that an end of a profunctor is isomorphic to a limit over \mathbf{Tw}(M).

Here we are interested in a coend, so we’ll have to slightly modify the proof. We’ll show that a coend is isomorphic to a colimit over the opposite catoegory \mathbf{Tw}^{op}(M^{op}). An object in this category is a triple (n, m, f \colon m \to n), in which the direction of the arrow is reversed. Morphisms are similarly reversed:

(n, m, f) \xleftarrow{(u, v)} (n', m', f')

They satisfy the commuting condition:

Cocones

A colimit is defined in terms of cocones. A cocone with a vertex V is a functor:

G \colon \mathbf{Tw}^{op}(M^{op}) \to \mathbf{Set}

together with a family of injections:

\tau_f \colon G (n, m, f) \to V.

Let’s define the functor G using our profunctor P. On objects, we have the obvious candidate:

G (m, n, f) = P (m, n)

The tricky part is to define the action of G on morphisms. The image, under G, of a morphism (u, v) is a function between sets:

G(u, v) \colon G(n', m', f') \to G (n, m, f)

We define it as:

G (u, v) = P (v, u)

The action of G is illustrated in this picture:

From Cocones to Cowedges

We can now establish a one-to-one correspondence between cocones and cowedges.

First of all, a cocone with a vertex V is built from a family of injections:

\tau_f \colon G(n, m, f) \to V

It’s easy to build the diagonal injections, coming from G (m, m, id_m). We make them equal to the cowedge injections:

\tau_{id_m} = \iota_m

A general injection \tau_f \colon G (n, m, f) \to V is given by either of the two formulas:

\tau_f = \iota_m \circ P (f, m) = \iota_n \circ P n f

which are equal by the wedge condition. This is illustrated by the following diagram:

Next we have to show that the triangles forming the sides of the cocone commute. Here’s one of such triangles:

The trick is to factorize the top morphism:

(n', m', f') \xrightarrow{(m', v)} (n, m', g) \xrightarrow{(u, n)} (n, m, f)

where g = f \circ u. Here, the identity morphisms are written as their corresponding objects, (m', v) = (id_{m'}, v), etc. This decomposition is illustrated in the following diagram:

Keep in mind the commuting condition in the definition of a twisted morphism:

f' = v \circ f \circ u = v \circ g

We can now factorize the top arrow of our triangle as follows:

G(n', m', f') \xrightarrow{ G(m', v)} G(n, m', g) \xrightarrow{G(u, n)} G(n, m, f)

We then decompose our triangle into a pair of triangles and the diamond. Translating between the functor G and the profunctor P, we build the following diagram:

The two triangles commute by functoriality, and the diamond is the cowedge for P. The mapping goes both ways: given a cocone (G, \tau) we can reconstruct the cowedge.

Finally, just like cowedges form a category, so do cocones; and we have just sketched the equivalence of the two categories. It follows that the terminal objects in the two categories are equivalent, therefore coends are isomorphic to colimits.

Twisted Optics

We can now give a precise meaning to the shorthand notation for optics:

O \underline s \; \underline a = \int^m (C \times D^{op})( \underline s, m \triangleright \underline a)

This is a colimit over the appropriate twisted arrow category:

O \, \underline s \; \underline a = \text{colim}_{m \colon \mathbf{Tw}^{op}(M^{op})} (C \times D^{op})( \underline s, m \triangleright \underline a)

The advantage of this definition is that it can be generalized to a double-categorical setting, where colimits have a precise meaning.

If you want to learn more about ends and coends, I recommend reading Coend Calculus by Fosco Loregian.