-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy path18-Ends.tex
1502 lines (1202 loc) · 72.4 KB
/
18-Ends.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass[DaoFP]{subfiles}
\begin{document}
\setcounter{chapter}{17}
\chapter{Ends and Coends}
\section{Profunctors}
In the rarified air of category theory we encounter patterns that are so far removed from their origins that we have problems visualizing them. It doesn't help that the more abstract a pattern gets the more dissimilar the concrete examples of it are.
An arrow from $a$ to $b$ is relatively easy to visualize. We have a very familiar model for it: a function that consumes elements of $a$ and produces elements of $b$. A hom-set is a collection of such arrows.
A functor is an arrow between categories. It consumes objects and arrows from one category and produces objects and arrows from another. We can think of it a recipe for building such objects (and arrows) from materials provided by the source category. In particular, we often think of an endofunctor as a container of building materials.
A profunctor maps a pair of objects $\langle a, b \rangle$ to a set $P\langle a, b \rangle$ and a pair of arrows:
\[ \langle f \colon s \to a, g \colon b \to t \rangle \]
to a function:
\[ P\langle f, g \rangle \colon P\langle a, b \rangle \to P\langle s, t \rangle\]
A profunctor is an abstraction that combines elements of many other abstractions. Since it's a functor $ \mathcal{C}^{op} \times \mathcal{C} \to \mathbf{Set}$, we can think of it as constructing a set from a pair of objects, and a function from a pair of arrows (one of them going in the opposite direction). This doesn't help our imagination though.
Fortunately, we have a good model for a profunctor: the hom-functor. The set of arrows between two objects behaves like a profunctor when you vary the objects. It also makes sense that there is a difference between varying the source and the target of the hom-set.
We can, therefore, think of an arbitrary profunctor as generalizing the hom-functor. A profunctor provides additional bridges between objects, on top of hom-sets that are already there.
There is, however one big difference between an element of the hom-set $ \mathcal{C}(a, b)$ and an element of the set $P\langle a, b \rangle$. Elements of hom-sets are arrows, and arrows can be composed. It's not immediately obvious how to compose profunctors.
Granted, the lifting of arrows by a profunctor can be seen as generalizing composition---just not between profuctors, but between hom-sets and profunctors. For instance, we can ``precompose'' $P \langle a, b \rangle$ with an arrow $f \colon s \to a$ to obtain $P \langle s, b \rangle$:
\[ P\langle f, id_b \rangle \colon P \langle a, b \rangle \to P \langle s, b \rangle \]
Similarly, we can ``postcompose'' it with $g \colon b \to t$:
\[ P \langle id_a, g \rangle \colon P \langle a, b \rangle \to P \langle a, t \rangle \]
This kind of heterogenous composition takes a composable pair consisting of an arrow and an element of a profunctor and produces an element of a profunctor.
A profunctor can be extended this way on both sides by lifting a pair of arrows:
\[
\begin{tikzcd}
& s
\arrow[r, bend left, dashed, blue, "f"]
& a
\arrow[r, bend right, "P"]
& b
\arrow[r, bend left, dashed, blue, "g"]
& t
\end{tikzcd}
\]
\subsection{Collages}
There is no reason to restrict a profunctor to a single category. We can easily define a profunctor between two categories as a functor $ P \colon \mathcal{C}^{op} \times \mathcal{D} \to \mathbf{Set}$. Such a profunctor can be used to glue two categories together by generating the missing hom-sets from the objects in $\mathcal{C}$ to the objects in $\mathcal{D}$.
A collage (or a \index{cograph}cograph) of two categories $\mathcal{C}$ and $\mathcal{D}$ is a category whose objects are objects from both categories (a disjoint union). A hom-set between two objects $x$ and $y$ is either a hom-set in $\mathcal{C}$, if both objects are in $\mathcal{C}$; a hom-set in $\mathcal{D}$, if both are in $\mathcal{D}$; or the set $P \langle x, y\rangle$ if $x$ is in $\mathcal{C}$ and $y$ is in $\mathcal{D}$. Otherwise the hom-set is empty.
Composition of morphisms is the usual composition, except if one of the morphisms is an element of $P \langle x, y \rangle$. In that case we lift the morphism we're trying to pre- or post-compose.
It's easy to see that a collage is indeed a category. The new morphisms that go between the two sides of the collage are sometimes called \index{heteromorphism}heteromorphisms. They can only go from $\mathcal{C}$ to $\mathcal{D}$, never the other way around.
Seen this way, a profunctor $ \mathcal{C}^{op} \times \mathcal{C} \to \mathbf{Set}$ should really be called an \emph{endo}-profunctor. It defines a collage of $\mathcal{C}$ with itself.
\begin{exercise}
Show that there is a functor from a collage of two categories to a stick-figure ``walking arrow'' category that has two objects and one arrow between them (and two identity arrows).
\end{exercise}
\begin{exercise}
Show that, if there is a functor from $\mathcal{C}$ to the walking arrow category then $\mathcal{C}$ can be split into a collage of two categories.
\end{exercise}
\subsection{Profunctors as relations}
Under a microscope, a profunctor looks like a hom-functor, and the elements of the set $P \langle a, b \rangle$ look like individual arrows. But when we zoom out, we can view a profunctor as a relation between objects. These are not the usual relations; they are \index{proof-relevant relation}\emph{proof-relevant} relations.
To understand this concept better, let's consider a regular functor $F \colon \mathcal{C} \to \mathbf{Set}$ (in other words, a co-presheaf). One way to interpret it is to say that it defines a \index{proof-relevant subset} subset of objects of $\mathcal{C}$, namely those objects that are mapped to non-empty sets. Every element of $F a$ is then treated as a proof that $a$ is a member of this subset. If, on the other hand, $F a$ is an empty set, then $a$ is not a member of the subset.
We can apply the same interpretation to profunctors. If the set $P \langle a, b \rangle$ is empty, we say that $b$ is not related to $a$. If it's not empty, we say that each element of the set $P \langle a, b \rangle$ represents a proof that $b$ is related to $a$. We can then treat a profunctor as a proof-relevant relation.
Notice that we don't assume anything about this relation. It doesn't have to be reflexive, as it's possible for $P \langle a, a \rangle$ to be empty (in fact, $P \langle a, a \rangle$ makes sense only for endo-profunctors). It doesn't have to be symmetric either.
Since the hom-functor is an example of an (endo-) profunctor, this interpretation lets us view the hom-functor in a new light: as a built-in proof-relevant relation between objects in a category. If there's an arrow between two objects, they are related. Notice that this relation is reflexive, since $\mathcal{C}(a, a)$ is never empty: at the very least, it contains the identity morphism.
Moreover, as we've seen before, hom-functors interact with profunctors. If $a$ is related to $b$ through $P$, and the hom-sets $\mathcal{C}(s, a)$ and $\mathcal{D}(b, t)$ are non-empty, then automatically $s$ is related to $t$ through $P$. Profunctors are therefore proof-relevant relations that are compatible with the structure of the categories in which they operate.
We know how to compose a profunctor with hom-functors, but how would we compose two profunctors? We can get a clue from the composition of relations.
Suppose that you want to charge your cellphone, but you don't have a charger. In order to connect you to a charger it's enough that you have a friend who owns a charger. Any friend will do. You compose the relation of having a friend with the relation of a person having a charger to get a relation of being able to charge your phone. The proof that you can charge your phone is a pair of proofs, one of friendship and one of the possession of a charger.
In general, we say that two objects are related by the composite relation if there exists an object in the middle that is related to both of them.
\subsection{Profunctor composition in Haskell}
Composition of relations can be translated to profunctor composition in Haskell. Let's first recall the definition of a profunctor:
\begin{haskell}
class Profunctor p where
dimap :: (s -> a) -> (b -> t) -> (p a b -> p s t)
\end{haskell}
The key to understanding profunctor composition is that it requires the \emph{existence} of the object in the middle. For object $b$ to be related to object $a$ through the composite $P \diamond Q$ there has to exist an object $x$ that bridges the gap:
\[
\begin{tikzcd}
& a
\arrow[r, bend left, blue, "Q"]
& x
\arrow[r, bend left, red, "P"]
& b
\end{tikzcd}
\]
This can be encoded in Haskell using an existential type. Given two profunctors \hask{p} and \hask{q}, their composition is a new profunctor \hask{Procompose p q}:
\begin{haskell}
data Procompose p q a b where
Procompose :: q a x -> p x b -> Procompose p q a b
\end{haskell}
We are using a \hask{GADT} to express the existential nature of the object \hask{x}. The two arguments to the data constructor can be seen as a pair of proofs: one proves that \hask{x} is related to \hask{a}, and the other that \hask{b} is related to \hask{x}. This pair then constitutes the proof that \hask{b} is related to \hask{a}.
An existential type can be seen as a generalization of a sum type. We are summing over all possible types \hask{x}. Just like a finite sum can be constructed by injecting one of the alternatives (think of the two constructors of \hask{Either}), the existential type can be constructed by picking one particular type for \hask{x} and injecting it into the definition of \hask{Procompose}.
Just as mapping out from a sum type requires a pair of function, one per each alternative; a mapping out from an existential type requires a family of functions, one per every type. The mapping out from \hask{Procompose}, for instance, is given by a polymorphic function:
\begin{haskell}
mapOut :: Procompose p q a b -> (forall x. q a x -> p x b -> c) -> c
mapOut (Procompose qax pxb) f = (f qax pxb)
\end{haskell}
The composition of profunctors is again a profunctor, as can be seen from this instance:
\begin{haskell}
instance (Profunctor p, Profunctor q) => Profunctor (Procompose p q)
where
dimap l r (Procompose qax pxb) =
Procompose (dimap l id qax) (dimap id r pxb)
\end{haskell}
This is just saying that you can extend the composite profunctor by extending the first one to the left and the second one to the right.
The fact that this definition of profunctor composition happens to work in Haskell is due to parametricity. The language constraints the types of profunctors in a way that makes this work. In general, though, taking a simple sum over intermediate objects would result in over-counting, so in category theory we have to compensate for that.
\section{Coends}
The over-counting in the naive definition of profunctor composition happens when two candidates for the object in the middle are connected by a morphism:
\[
\begin{tikzcd}
& a
\arrow[r, bend left, blue, "Q"]
&x
\arrow[r, dashed, "f"]
& y
\arrow[r, bend left, red, "P"]
& b
\end{tikzcd}
\]
We can either extend $Q$ on the right, by lifting $Q \langle id, f \rangle$, and use $y$ as the middle object; or we can extend $P$ on the left, by lifting $P \langle f, id \rangle$, and use $x$ as the intermediary.
In order to avoid the double-counting, we have to tweak our definition of a sum type when applied to profunctors. The resulting construction is called a coend.
First, let's re-formulate the problem. We are trying to sum over all objects $x$ in the product:
\[ P \langle a, x \rangle \times Q \langle x, b \rangle \]
The double-counting happens because we can open up the gap between the two profunctors, as long as there is a morphism that we can fit between them. So we are really looking at a more general product:
\[ P \langle a, x \rangle \times Q \langle y, b \rangle \]
The important observation is that, if we fix the endpoints $a$ and $b$, this product is a profunctor in $\langle y, x \rangle$. This is easily seen after a little rearrangement (up to isomorphism):
\[ Q \langle y, b \rangle \times P \langle a, x \rangle \]
We are interested in the sum of the diagonal parts of this profunctor, that is when $x$ is equal to $y$.
So let's see how we would go about defining the sum of all diagonal entries of a general profunctor $P$. In fact, this construction works for any functor $P \colon \cat C^{op} \times \cat C \to D$, not just for $\Set$-valued profunctors.
The sum of the diagonal objects is defined by injections; in this case, one per every object in $\cat C$. Here we show just two of them and the dashed line representing all the rest:
\[
\begin{tikzcd}
P \langle y, y \rangle
\arrow[dr, "i_y"']
\arrow[rr, dash, dashed]
&&P \langle x, x \rangle
\arrow[dl, "i_x"]
\\
& d
\end{tikzcd}
\]
If we were defining a sum, we'd make it a universal object equipped with such injections. But because we are dealing with functors of two variables, we want to identify the injections that are related by ``extending'' some common ancestor---here, $P \langle y, x \rangle$. We want the following diagram to commute, whenever there is a connecting morphism $f\colon x \to y$:
\[
\begin{tikzcd}
&P \langle y, x \rangle
\arrow[ld, "{P \langle id, f \rangle}"']
\arrow[rd, "{P \langle f, id \rangle}"]
\\
P \langle y, y \rangle
\arrow[dr, "i_y"']
&&P \langle x, x \rangle
\arrow[dl, "i_x"]
\\
&d
\end{tikzcd}
\]
This diagram is called a \index{co-wedge}co-wedge, and its commuting condition is called the co-wedge condition. For every $f \colon x \to y$, we demand that:
\[ i_x \circ P \langle f, id_y \rangle = i_y \circ P \langle id_x, f \rangle \]
The \emph{universal} co-wedge is called a coend.
Since a coend generalizes the sum to a potentially infinite domain, we write it using the integral sign, with the ``integration variable'' at the top:
\[ \int^{x\colon \mathcal{C}} P \langle x, x \rangle \]
Universality means that, whenever there is an object $d$ in $\cat D$ equipped with a family of arrows $g_x \colon P \langle x, x \rangle \to d$ satisfying the co-wedge condition, there is a unique mapping out from the coend:
\[ h \colon \int^{x\colon \mathcal{C}} P \langle x, x \rangle \to d \]
that factorizes every $g_x$ through the injection $i_x$:
\[ g_x = h \circ i_x \]
Pictorially, we have:
\[
\begin{tikzcd}
&P \langle y, x \rangle
\arrow[ld, "{P \langle id, f \rangle}"']
\arrow[rd, "{P \langle f, id \rangle}"]
\\
P \langle y, y \rangle
\arrow[dr, "i_y"']
\arrow[ddr, bend right, "g_y"']
&&P \langle x, x \rangle
\arrow[dl, "i_x"]
\arrow[ddl, bend left, "g_x"]
\\
&\int^x P \langle x, x \rangle
\arrow[d, dashed, "h"]
\\
&d
\end{tikzcd}
\]
Compare this with the definition of a sum of two objects:
\[
\begin{tikzcd}
a
\arrow[dr, "\text{Left}"]
\arrow[ddr, bend right, "f"']
&& b
\arrow[dl, "\text{Right}"']
\arrow[ddl, bend left, "g"]
\\
&a + b
\arrow[d, dashed, "h"]
\\
& d
\end{tikzcd}
\]
Just like the sum was defined as a universal cospan, a coend is defined as a universal co-wedge.
In particular, if you were to construct a coend of a $\Set$-valued profunctor, you would start with a sum (a discriminated union) of all the sets $P \langle x, x \rangle$. Then you would identify all the elements of this sum that satisfy the co-wedge condition. You'd identify the element $a \in P \langle x, x \rangle$ with the element $b \in P \langle y, y \rangle$ whenever there is an element $c \in P \langle y, x \rangle$ and a morphism $f \colon x \to y$, such that:
\[ P \langle id, f \rangle (c) = b\]
and
\[ P \langle f, id \rangle (c) = a\]
Notice that, in a discrete category (which is just a set of objects with no arrows between them) the co-wedge condition is trivial (there are no $f$'s other than identities), so a coend is just a straightforward sum (coproduct) of the diagonal objects $P \langle x, x \rangle$.
\subsection{Extranatural transformations}
A family of arrows in the target category parameterized by the objects of the source category can often be combined into a single natural transformation between two functors.
The injections in our definition of a cowedge form a family of functions that is parameterized by objects, but they don't neatly fit into a definition of a natural transformation.
\[
\begin{tikzcd}
P \langle y, y \rangle
\arrow[dr, "i_y"']
\arrow[rr, dash, dashed]
&&P \langle x, x \rangle
\arrow[dl, "i_x"]
\\
&d
\end{tikzcd}
\]
The problem is that the functor $P \colon \cat C^{op} \times \cat C \to \cat D$ is contravariant in the first argument and covariant in the second; so its diagonal part, which on objects is defined as $x \mapsto P \langle x, x \rangle$, is neither.
The closest analog of naturality at our disposal is the cowedge condition:
\[
\begin{tikzcd}
&P \langle y, x \rangle
\arrow[ld, "{P \langle id, f \rangle}"']
\arrow[rd, "{P \langle f, id \rangle}"]
\\
P \langle y, y \rangle
\arrow[dr, "i_y"']
&&P \langle x, x \rangle
\arrow[dl, "i_x"]
\\
&d
\end{tikzcd}
\]
Indeed, as is the case with the naturality square, it involves the interaction between the lifting of a morphism $f \colon x \to y$ (here, in two different ways) and the components of the transformation $i$.
Granted, the standard naturality condition deals with pairs of functors. Here, the target of the transformation is a fixed object $d$. But we can always reinterpret it as the output of a constant profunctor $\Delta_d \colon \cat C^{op} \times \cat C \to \cat D$. Thus to generalize naturality, we replace $\Delta_d$ with an arbitrary profunctor $Q$.
We reinterpret the cowedge condition as a special case of the more general \index{extranatural transformation}\emph{extranatural} transformation. An extranatural transformation is a family of arrows:
\[ \alpha_{c d} \colon P \langle c, c \rangle \to Q \langle d, d \rangle \]
between two functors of the form:
\[ P \colon \cat C^{op} \times \cat C \to \cat E \]
\[ Q \colon \cat D^{op} \times \cat D \to \cat E \]
Extranaturality in $c$ means that the following diagram commutes for any morphism $f \colon c \to c'$:
\[
\begin{tikzcd}
&P \langle c', c \rangle
\arrow[ld, "{P \langle id, f \rangle}"']
\arrow[rd, "{P \langle f, id \rangle}"]
\\
P \langle c', c' \rangle
\arrow[dr, "\alpha_{c' d}"']
&&P \langle c, c \rangle
\arrow[dl, "\alpha_{c d}"]
\\
& Q \langle d, d \rangle
\end{tikzcd}
\]
Extranaturality in $d$ means that the following diagram commutes for any morphism $g \colon d \to d'$:
\[
\begin{tikzcd}
&P \langle c, c \rangle
\arrow[ld, "\alpha_{c d}"']
\arrow[rd, "\alpha_{c d'}"]
\\
Q \langle d, d \rangle
\arrow[dr, "{Q \langle id, g\rangle}"']
&&Q \langle d', d' \rangle
\arrow[dl, "{Q \langle g, id\rangle}"]
\\
& Q \langle d, d' \rangle
\end{tikzcd}
\]
Given this definition, we get our cowedge condition as the extranaturality of the mapping between the profunctor $P$ and the constant profunctor $\Delta_d$.
We can now reformulate the definition of the coend as a pair $(c, i)$ where $c$ is the object equipped with the extranatural transformation $i \colon P \to \Delta_c$ that is universal among such pairs.
Universality means that for any object $d$ equipped with the extranatural transformation $\alpha \colon P \to \Delta_d$ there is a unique morphism $h \colon c \to d$ that factorizes all the components of $\alpha$ through the components of $i$:
\[ \alpha_x = h \circ i_x \]
We call this object $c$ the coend, and write it as:
\[ c = \int^x P\langle x, x \rangle \]
\begin{exercise}
Verify that that, for the extranatural transformation $P \to \Delta_d$, the first extranaturality diamond is equivalent to the cowedge condition, and the second is trivially satisfied.
\end{exercise}
\subsection{Profunctor composition using coends}
Equipped with the definition of a coend we can now formally define the composition of two profunctors:
\[ (P \diamond Q)\langle a, b \rangle = \int^{x\colon \mathcal{C}} Q \langle a, x \rangle \times P \langle x, b \rangle\]
Compare this with:
\begin{haskell}
data Procompose p q a b where
Procompose :: q a x -> p x b -> Procompose p q a b
\end{haskell}
The reason why in Haskell we don't have to worry about the co-wedge condition is analogous to the reason why all parametrically polymorphic functions automatically satisfy naturality condition. A coend is defined using a family of injections; in Haskell all these injections are defined by a \emph{single} polymorphic function:
\begin{haskell}
data Coend p where
Coend :: p x x -> Coend p
\end{haskell}
\index{parametricity}Parametricity then enforces the co-wedge condition.
Coends introduce a new level of abstraction in dealing with profunctors. Calculations using coends usually take advantage of their mapping-out property. To define a mapping out of a coend to some object $d$:
\[ \int^x P \langle x, x \rangle \to d \]
it's enough to define a family of functions from the diagonal entries of the functor to $d$:
\[ g_x \colon P \langle x, x \rangle \to d \]
satisfying the cowedge condition. You can get a lot of mileage from this trick, especially when combined with the Yoneda lemma. We'll see examples of this in what follows.
\begin{exercise}
Define a \hask{Profunctor} instance for the pair of profunctors:
\begin{haskell}
newtype ProPair q p a b x y = ProPair (q a y, p x b)
\end{haskell}
Hint: Keep the first four parameters fixed:
\begin{haskell}
instance (Profunctor p, Profunctor q) => Profunctor (ProPair q p a b)
\end{haskell}
\end{exercise}
\begin{exercise}
Profunctor composition can be expressed using a coend:
\begin{haskell}
newtype CoEndCompose p q a b = CoEndCompose (Coend (ProPair q p a b))
\end{haskell}
Define a \hask{Profunctor} instance for \hask{CoEndCompose}.
\end{exercise}
\subsection{Colimits as coends}
A function of two variables that ignores one of its arguments is equivalent to a function of one variable. Similarly, a profunctor that ignores one of its arguments is equivalent to a functor. Conversely, given a functor $F$, we can construct a trivial profunctor. Its action on objects is given by:
\[P \langle x, y \rangle = F y \]
Its action on a pair of arrows ignores one of the arrows:
\[P \langle f, g \rangle = F g \]
For any $f \colon x \to y$, our definition of a coend for such a profunctor reduces to the following diagram:
\[
\begin{tikzcd}
& F x
\arrow[ld, "F f"']
\arrow[rd, dashed, "id_{F x}"]
\\
F y
\arrow[dr, "i_y"']
\arrow[ddr, bend right, "g_y"']
&& F x
\arrow[dl, "i_x"]
\arrow[ddl, bend left, "g_x"]
\\
&\int^x F x
\arrow[d, dashed, "h"]
\\
&d
\end{tikzcd}
\]
After shrinking the identity arrows, the original co-wedge becomes a co-cone, and the universal condition turns into the definition of a colimit. This justifies the use the coend notation for colimits:
\[ \int^x F x = \text{colim} F \]
The functor $F$ defines a diagram in the target category. The pattern is the whole source category.
We can gain useful intuition if we consider a discrete category, in which a profunctor is a (possibly infinite) matrix and a coend is the sum (coproduct) if its diagonal elements. A profunctor that is constant along one axis corresponds to a matrix whose rows are identical (each given by a ``vector'' $F x$). The sum of the diagonal elements of such a matrix is equal to the sum of all components of the vector $F x$.
\[
\begin{pmatrix}
\color{red} F a & F b & F c & ... \\
F a & \color{red}F b & F c & ...\\
F a & F b &\color{red}F c & ...\\
... & ... & ... & ...
\end{pmatrix}
\]
In a non-discrete category, this sum generalizes to a colimit.
\section{Ends}
Just like a coend generalizes the sum of the diagonal elements of a profunctor---its dual, an end, generalizes the product. A product is defined by its projections, and so is an end.
The generalization of a span that we used in the definition of a product would be an object $d$ with a family of projections, one per every object $x$:
\[ \pi_x \colon d \to P \langle x, x \rangle \]
The dual to a co-wedge is called a \index{wedge}wedge:
\[
\begin{tikzcd}
&d
\arrow[ld, "\pi_x"']
\arrow[rd, "\pi_y"]
\\
P \langle x, x \rangle
\arrow[dr, "{P \langle id, f \rangle}"']
&&P \langle y, y \rangle
\arrow[dl, "{P \langle f, id \rangle}"]
\\
& P \langle x, y \rangle
\end{tikzcd}
\]
For every arrow $f \colon x \to y$ we demand that:
\[ P \langle f, id_y \rangle \circ \pi_y = P \langle id_x, f \rangle \circ \pi_x \]
The end is a universal wedge. We use the integral sign for it too, this time with the ``integration variable'' at the bottom.
\[ \int_{x \colon \cat C} P \langle x, x \rangle \]
You might be wondering why, in calculus, integrals based on multiplication rather than summation are rarely used. That's because we can always use a logarithm to replace multiplication with addition. We don't have this luxury in category theory, so ends and coends are equally important.
To summarize, an end is an object equipped with a family of morphisms (projections):
\[ \pi_a \colon \left( \int_x P \langle x, x \rangle \right) \to P \langle a, a \rangle \]
satisfying the wedge condition.
It is universal among such objects; that is, for any other object $d$ equipped with a family of arrows $g_x$ satisfying the wedge condition, there is a unique morphism $h$ that factorizes the family $g_x$ through the family $\pi_x$:
\[ g_x = \pi_x \circ h \]
Pictorially, we have:
\[
\begin{tikzcd}
&d
\arrow[ddl, bend right, "g_x"']
\arrow[ddr, bend left, "g_y"]
\arrow[d, dashed, "h"]
\\
& \int_x P \langle x, x \rangle
\arrow[ld, "\pi_x"']
\arrow[rd, "\pi_y"]
\\
P \langle x, x \rangle
\arrow[dr, "{P \langle id, f \rangle}"']
&&P \langle y, y \rangle
\arrow[dl, "{P \langle f, id \rangle}"]
\\
& P \langle x, y \rangle
\end{tikzcd}
\]
Equivalently, we can say that the end is a pair $(e, \pi)$ consisting of an object $e = \int_x P\langle x, x\rangle$ and an \index{extranatural transformation}extranatural transformation $\pi \colon \Delta_d \to e$ that is universal among such pairs. The wedge condition turns out to be a special case of extranaturality condition.
If you were to construct an end of a $\Set$-valued profunctor, you'd start with a giant product of all $P \langle x, x \rangle$ for all objects in the category $\cat C$, and then prune the tuples that don't satisfy the wedge condition.
In particular, imagine using the singleton set $1$ in place of $d$. The family $g_x$ would select one element from each set $P \langle x, x \rangle$. This would give you a giant tuple. You'd weed out most of these tuples, leaving only the ones that satisfy the wedge condition.
Again, in Haskell, due to \index{parametricity}parametricity, the wedge condition is automatically satisfied, and the definition of the end for a profunctor \hask{p} simplifies to:
\begin{haskell}
type End p = forall x. p x x
\end{haskell}
The Haskell implementation of an \hask{End} doesn't showcase the fact that it is dual to the \hask{Coend}. This is because, at the time of this writing, Haskell doesn't have a built-in syntax for existential types. If it did, the \hask{Coend} would be implemented as:
\begin{haskell}
type Coend p = exists x. p x x
\end{haskell}
The existential/universal duality between a \hask{Coend} and an \hask{End} means that it's easy to construct a \hask{Coend}---all you need is to pick one type \hask{x} for which you have a value of the type \hask{p x x}. On the other end, to construct an \hask{End} you have to provide a whole family of values \hask{p x x}, one for every type \hask{x}. In other words, you need a polymorphic formula that is parameterized by \hask{x}. A definition of a polymorphic function is a canonical example of such a formula.
\subsection{Natural transformations as an end}
The most interesting application of an end is in concisely defining the set of natural transformations. Consider two functors, $F$ and $G$, going between two categories $\mathcal{B}$ and $\mathcal{C}$. A natural transformation between them is a family of arrows $\alpha_x$ in $\mathcal{C}$. You may think of it as picking one element $\alpha_x$ from each hom-set $\mathcal{C} (F x, G x)$.
\[
\begin{tikzcd}
&& F x
\arrow[dd, "{\alpha_x \in \cat C (F x, G x)}"]
\\
x
\arrow[urr, dashed, "F"]
\arrow[drr, dashed, "G"]
\\
&& G x
\end{tikzcd}
\]
We know that the mapping $\langle a, b \rangle \to \mathcal{C} (a, b)$ defines a profunctor. It turns out that, for any pair of functors, the mapping $\langle a, b \rangle \to \mathcal{C} (F a, G b)$ also behaves like a profunctor. The action of this profunctor on a pair of arrows $\langle f \colon s \to a, g \colon b \to t \rangle$ is a function:
\[ \cat C(F a, G b) \to \cat C (F s, G t) \]
given by the composition:
\[ F s \xrightarrow{F f} F a \xrightarrow{h} G b \xrightarrow{G g} G t \]
where $h$ is an element of $ \mathcal{C} (F a, G b)$.
The diagonal parts of this profunctor are perfect candidates for the components of a natural transformation. In fact, the end:
\[ \int_{x \colon \mathcal{B}} \mathcal{C}(F x, G x) \]
defines a set of natural transformations from $F$ to $G$.
To show this, let's check the wedge condition. Plugging in our profunctor, we get:
\[
\begin{tikzcd}
& \int_{x} \mathcal{C}(F x, G x)
\arrow[ld, "\pi_a"']
\arrow[rd, "\pi_b"]
\\
\mathcal{C} ( F a, G a )
\arrow[dr, "{(Ff \, \circ \, -)}"']
&& \mathcal{C} \langle F b, G b \rangle
\arrow[dl, "{(- \, \circ\, Gf)}"]
\\
& \mathcal{C} ( F a, G b )
\end{tikzcd}
\]
We can pick a single element of the set $\int_{x} \mathcal{C}(F x, G x)$ by instantiating the universal condition for the singleton set:
\[
\begin{tikzcd}
& 1
\arrow[d, dashed, "\alpha"]
\arrow[ddl, bend right, "\alpha_a"']
\arrow[ddr, bend left, "\alpha_b"]
\\
& \int_{x} \mathcal{C}(F x, G x)
\arrow[ld, "\pi_a"']
\arrow[rd, "\pi_b"]
\\
\mathcal{C} ( F a, G a )
\arrow[dr, "{(F f \, \circ \, -)}"']
&& \mathcal{C} ( F b, G b )
\arrow[dl, "{(- \, \circ\, G f)}"]
\\
& \mathcal{C} ( F a, G b )
\end{tikzcd}
\]
We pick the component $\alpha_a$ from the hom-set $\mathcal{C} ( F a, G a )$ and the component $\alpha_b$ from $\mathcal{C} ( F b, G b )$. The wedge condition then boils down to:
\[ F f \circ \alpha_a = \alpha_b \circ G f \]
for any $f \colon a \to b$. This is exactly the naturality condition. So any element $\alpha$ of this end is automatically a natural transformation.
The set of natural transformations, or the hom-set in the functor category, is thus given by the end:
\[ [\mathcal{C}, \mathcal{D}] (F, G) \cong \int_{x \colon \mathcal{B}} \mathcal{C}(F x, G x)\]
In Haskell, this is consistent with our earlier definition:
\begin{haskell}
type Natural f g = forall x. f x -> g x
\end{haskell}
As we discussed earlier, to construct an \hask{End} we have to give it a whole family of values parameterized by types. Here, these values are the components of a polymorphic function.
\subsection{Limits as ends}
Just like we were able to express colimits as coends, we can express limits as ends. As before, we define a trivial profunctor that ignores its first argument:
\begin{align*}
P \langle x, y \rangle &= F y \\
P \langle f, g \rangle &= F g
\end{align*}
The universal condition that defines an end becomes the definition of a universal cone:
\[
\begin{tikzcd}
&d
\arrow[ddl, bend right, "g_x"']
\arrow[ddr, bend left, "g_y"]
\arrow[d, dashed, "h"]
\\
& \int_x F x
\arrow[ld, "\pi_x"']
\arrow[rd, "\pi_y"]
\\
F x
\arrow[dr, "F f"']
&&F y
\arrow[dl, dashed, "id_{F y}"]
\\
& F y
\end{tikzcd}
\]
We can thus use the end notation for limits:
\[ \int_x F x = \text{lim} F \]
\begin{exercise}
A product is a limit of a functor from a two-object category $\Cat 2$. Show that it can be defined as an end. Hint: There are no non-identity morphisms in $\Cat 2$.
\end{exercise}
\section{Continuity of the Hom-Functor}
In category theory, a functor $F$ is called \index{continuous functor}\emph{continuous} if it preserves limits (and co-continuous, if it preserves colimits). It means that, if you have a diagram in the source category, it doesn't matter if you first use $F$ to map the diagram and then take the limit in the target category, or take the limit in the source category and then use $F$ to map this limit.
The hom-functor is an example of a functor that is continuous in its second argument. Since a product is the simplest example of a limit, this means, in particular, that:
\[ \mathcal{C}(x, a \times b) \cong \mathcal{C}(x, a) \times \mathcal{C}(x, b) \]
The left hand side applies the hom-functor to the product (a limit of a span). The right hand side maps the diagram, here just a pair of objects, and takes the product (limit) in the target category. The target category for the hom-functor is $\mathbf{Set}$, so this is just a cartesian product. The two sides are isomorphic by the universal property of the product: the mapping into the product is defined by a pair of mappings into the two objects.
Continuity of the hom-functor in the first argument is reversed: it maps colimits to limits. Again, the simplest example of a colimit is the sum, so we have:
\[ \mathcal{C}(a + b, x) \cong \mathcal{C}(a, x) \times \mathcal{C}(b, x) \]
This follows from the universality of the sum: a mapping out of the sum is defined by a pair of mapping out of the two objects.
It can be shown that an end can be expressed as a limit, and a coend as a colimit. Therefore, by continuity of the hom-functor, we can always pull out the integral sign from inside a hom-set. By analogy with the product, we have the mapping-in formula for an end:
\[\cat D\left(d, \int_a P\langle a, a \rangle \right) \cong \int_a \cat D(d, P\langle a, a \rangle) \]
By analogy with the sum, we have a mapping-out formula for the coend:
\[\cat D\left( \int^a P\langle a, a \rangle , d \right) \cong \int_a \cat D(P\langle a, a \rangle, d) \]
Notice that, in both cases, the right-hand side is an end.
\section{Fubini Rule}
The Fubini rule in calculus states the conditions under which we can switch the order of integration in double integrals. It turns out that we can similarly switch the order of double ends and coends. The \index{Fubini rule}Fubini rule for ends works for functors of the form $P \colon \cat C \times \cat C^{op} \times \cat D \times \cat D^{op} \to \cat E$. The following expressions, as long as they exist, are isomorphic:
\[ \int_{c \colon \cat C} \int_{d \colon \cat D} P\langle c, c \rangle \langle d, d \rangle \cong \int_{d \colon \cat D} \int_{c \colon \cat C} P\langle c, c \rangle \langle d, d \rangle \cong \int_{\langle c, d \rangle \colon \cat C \times \cat D} P\langle c, c \rangle \langle d, d \rangle \]
In the last end, the functor $P$ is reinterpreted as $P \colon (\cat C \times \cat D)^{op} \times (\cat C \times \cat D)\to \cat E$
The analogous rule works for coends as well.
\section{Ninja Yoneda Lemma}
Having expressed the set of natural transformations as an end, we can now rewrite the Yoneda lemma. This is the original formulation:
\[ [\mathcal{C}, \mathbf{Set}]( \mathcal{C}(a, -), F) \cong F a \]
Here, $F$ is a (covariant) functor from $\mathcal{C}$ to $\mathbf{Set}$ (a co-presheaf), and so is the hom-functor $\mathcal{C}(a, -)$.
Expressing the set of natural transformations as an end we get:
\[ \int_{x \colon \mathcal{C}} \mathbf{Set} (\mathcal{C}(a, x), F x) \cong F a \]
Similarly, we have the Yoneda lemma for a contravariant functor (a presheaf) $G$:
\[ \int_{x \colon \mathcal{C}} \mathbf{Set} (\mathcal{C}(x, a), G x) \cong G a \]
These versions of the Yoneda lemma, expressed in terms of ends, are often half-jokingly called ninja-Yoneda lemmas. The fact that the ``integration variable'' is explicit makes them somewhat easier to use in complex formulas.
There is also a dual set of ninja co-Yoneda lemmas that use coends instead. For a covariant functor, we have:
\[ \int^{x \colon \mathcal{C}} \mathcal{C}(x, a) \times F x \cong F a \]
and for the contravariant one we have:
\[ \int^{x \colon \mathcal{C}} \mathcal{C}(a, x) \times G x \cong G a \]
Physicists might notice the similarity of these formulas to integrals involving the Dirac delta function---strictly speaking, a distribution. This is why profunctors are sometimes called \index{distributors}distributors, following the adage that ``distributors are to functors as distributions are to functions.'' Engineers might notice the similarity of the hom-functor to the impulse function.
This intuition is often expressed by saying that we can perform the ``integration over $x$'' in this formula, resulting in replacing $x$ with $a$ in the integrand $G x$.
If $\cat C$ is a discrete category, the coend reduces to the sum (coproduct), and the hom-functor reduces to the unit matrix (the Kronecker delta). The co-Yoneda lemma then becomes:
\[ \sum_j \delta_i^j v_j = v_i \]
In fact, a lot of linear algebra translates directly to the theory of $\Set$-valued functors. You may often view such functors as vectors in a vector space, in which hom-functors form a basis. Profunctors become matrices and coends are used to multiply such matrices, calculate their traces, or multiply vectors by matrices.
Yet another name for profunctors, especially in Australia, is \index{bimodule}``bimodules.'' This is because the lifting of morphisms by a profunctor is somewhat similar to the left and right actions on sets.
We'll now proceed with the proof of the co-Yoneda lemma, which is quite instructive, as it uses a few common tricks. Most importantly, we rely on the corollary of the Yoneda lemma, which says that, if all the mappings out from two objects to an arbitrary object are isomorphic, then the two objects are themselves isomorphic. In our case, we'll consider the mappings-out to an arbitrary set $S$ and show that:
\[ \mathbf{Set} \left(\int^{x \colon \mathcal{C}} \mathcal{C}(x, a) \times F x, S \right) \cong
\Set (F a, S)\]
Using the co-continuity of the hom-functor, we can pull out the integral sign, replacing the coend with an end:
\[ \int_{x \colon \mathcal{C}} \mathbf{Set} \left( \mathcal{C}(x, a) \times F x, S \right) \]
Since the category of sets is cartesian closed, we can curry the product:
\[ \int_{x \colon \mathcal{C}} \mathbf{Set} \left( \mathcal{C}(x, a) , S^{F x} \right) \]
We can now use the Yoneda lemma to ``integrate over $x$.'' The result is $S^{F a}$. Finally, in $\mathbf{Set}$, the exponential object is isomorphic to the hom-set:
\[S^{F a} \cong \mathbf{Set}(F a, S)\]
Since $S$ was arbitrary, we conclude that:
\[ \int^{x \colon \mathcal{C}} \mathcal{C}(x, a) \times F x \cong F a \]
\begin{exercise}
Prove the contravariant version of the co-Yoneda lemma.
\end{exercise}
\subsection{Yoneda lemma in Haskell}
We've already seen the Yoneda lemma implemented in Haskell. We can now rewrite it in terms of an end. We start by defining a profunctor that will go under the end. Its type constructor takes a functor \hask{f} and a type \hask{a} and generates a profunctor that's contravariant in \hask{x} and covariant in \hask{y}:
\begin{haskell}
data Yo f a x y = Yo ((a -> x) -> f y)
\end{haskell}
The Yoneda lemma establishes the isomorphism between the end over this profunctor and the type obtained by acting with the functor \hask{f} on \hask{a}. This isomorphism is witnessed by a pair of functions:
\begin{haskell}
yoneda :: Functor f => End (Yo f a) -> f a
yoneda (Yo g) = g id
yoneda_1 :: Functor f => f a -> End (Yo f a)
yoneda_1 fa = Yo (\h -> fmap h fa)
\end{haskell}
Similarly, the co-Yoneda lemma uses a coend over the following profunctor:
\begin{haskell}
data CoY f a x y = CoY (x -> a) (f y)
\end{haskell}
The isomorphism is witnessed by a pair of functions. The first one says that if you have a function \hask{x -> a} and a functorful of \hask{x} then you can make a functorful of \hask{a} using the \hask{fmap}:
\begin{haskell}
coyoneda :: Functor f => Coend (CoY f a) -> f a
coyoneda (Coend (CoY g fa)) = fmap g fa
\end{haskell}
You can do it without knowing anything about the existential type \hask{x}.
The second says that if you have a functorful of \hask{a}, you can create a coend by injecting it (together with the identity function) into the existential type:
\begin{haskell}
coyoneda_1 :: Functor f => f a -> Coend (CoY f a)
coyoneda_1 fa = Coend (CoY id fa)
\end{haskell}
\section{Day Convolution}
Electrical engineers are familiar with the idea of convolution. We can convolve two streams by shifting one of them and summing its product with the other one:
\[ (f \star g)(x) = \int^{\infty}_{-\infty} f(y) g(x - y) dy \]
This formula can be translated almost verbatim to category theory. We can start by replacing the integral with a coend. The problem is, we don't know how to subtract objects. We do however know how to add them, in a co-cartesian category.
Notice that the sum of the arguments to the two functions is equal to $x$. We could enforce this condition by introducing the Dirac delta function or the ``impulse function,'' $\delta(a + b - x)$. In category theory we use the hom-functor $\cat C (a + b, x)$ to do the same. Thus we can define a convolution of two $\Set$-valued functors:
\[ (F \star G) x = \int^{a, b} \cat C (a + b, x) \times F a \times G b \]
Informally, if we could define subtraction as the right adjoint to coproduct, we'd write:
\[ \int^{a, b} \cat C (a + b, x) \times F a \times G b \cong \int^{a, b} \cat C (a, b - x) \times F a \times G b \cong \int^b F (b - x) \times G b\]
There is nothing special about coproduct so, in general, Day convolution is defined in any monoidal category with a tensor product:
\[ (F \star G) x = \int^{a, b} \cat C (a \otimes b, x) \times F a \times G b \]
In fact, Day convolution for a monoidal category $(\cat C, \otimes, I)$ endows the category of co-presheaves $[\cat C, \Set]$ with a monoidal structure. Simply said, if you can multiply objects in $\cat C$, you can multiply set-valued functors on $\cat C$.
It's easy to check that Day convolution is associative (up to isomorphism) and that $\cat C(I, -)$ serves as the unit object. For instance, we have:
\[ (\cat C(I, -) \star G) x = \int^{a, b} \cat C (a \otimes b, x) \times \cat C(I, a) \times G b \cong
\int^{b} \cat C (I \otimes b, x) \times G b \cong G x\]
So the unit of Day convolution is the Yoneda functor taken at monoidal unit, which lends itself to the anagrammatic slogan, ``ONE of DAY is the YONEDA of ONE.''
If the tensor product is symmetric, then the corresponding Day convolution is also symmetric (up to isomorphism).
In the special case of a cartesian closed category, we can use the currying adjunction to simplify the formula:
\[ (F \star G) x = \int^{a, b} \cat C (a \times b, x) \times F a \times G b \cong \int^{a, b} \cat C (a, x^b) \times F a \times G b \cong \int^{b} F (x^b) \times G b\]
In Haskell, the product-based Day convolution can be defined using an existential type:
\begin{haskell}
data Day f g x where
Day :: ((a, b) -> x) -> f a -> g b -> Day f g x
\end{haskell}
If we think of functors as containers of values, Day convolution tells us how to combine two different containers into one---given a function that combines two different values into one.
\begin{exercise}
Define the \hask{Functor} instance for \hask{Day}.
\end{exercise}
\begin{exercise}
Implement the associator for \hask{Day}.
\begin{haskell}
assoc :: Day f (Day g h) x -> Day (Day f g) h x
\end{haskell}
Hint: When constructing the result, you are free to pick an existential type at your convenience, e.g., it could be a pair type.
\end{exercise}
\subsection{Applicative functors as monoids}
We've seen before the definition of applicative functors as lax monoidal functors. It turns out that, just like monads, applicative functors can also be defined as monoids.
Recall that a monoid is an object in a monoidal category. The category we're interested in is the co-presheaf category $[\cat C, \Set]$. If $\cat C$ is cartesian, then the co-presheaf category is monoidal with respect to Day convolution, with the unit object $\cat C(I, -)$. A monoid in this category is a functor $F$ equipped with two natural transformations that serve as unit and multiplication:
\[ \eta \colon \cat C(I, -) \to F \]
\[ \mu \colon F \star F \to F \]
In particular, in a cartesian closed category where the unit is the terminal object, $\cat C(1, a)$ is isomorphic to $a$, and the component of the unit at $a$ is:
\[ \eta_a \colon a \to F a \]
You may recognize this function as \hask{pure} in the definition of \hask{Applicative}.
\begin{haskell}
pure :: a -> f a
\end{haskell}
Let's consider the set of natural transformations from which $\mu$ is taken. We'll write it as an end:
\[ \mu \in \int_x \Set \big( (F \star F) x, F x \big) \]
Pluggin in the definition of Day convolution, we get:
\[ \int_x \Set \big( \int^{a, b} \cat C (a \times b, x) \times F a \times F b, F x \big) \]
We can pull out the coend using co-continuity of the hom-functor:
\[ \int_{x, a, b} \Set \big( \cat C (a \times b, x) \times F a \times F b, F x \big) \]
We can then use the currying adjunction in $\Set$ to obtain:
\[ \int_{x, a, b} \Set \big( \cat C (a \times b, x), \Set( F a \times F b, F x) \big) \]
Finally, we apply the Yoneda lemma to perform the integration over $x$:
\[ \int_{a, b} \Set \big( F a \times F b, F (a \times b) \big) \]
The result is the set of natural transformations from which to select the second part of the lax monoidal functor:
\begin{haskell}
(>*<) :: f a -> f b -> f (a, b)
\end{haskell}
\subsection{Free Applicatives}
We have just learned that applicative functors are monoids in the monoidal category:
\[ ([\cat C, \Set], \cat C(I, -), \star) \]
It's only natural to ask what a free monoid in that category is.
Just like we did with free monads, we'll construct a free applicative as the initial algebra, or the least fixed point of the list functor. Recall that the list functor was defined as:
\[ \Phi_a x = 1 + a \otimes x \]
In our case it becomes:
\[ \Phi_F G = \cat C(I, -) + F \star G \]
Its fixed point is given by the recursive formula:
\[ A_F \cong \cat C(I, -) + F \star A_F\]
When translating this to Haskell, we observe that functions from the unit \hask{()->a} are isomorphic to elements of \hask{a}.
Corresponding to the two addends in the definition of $A_F$, we get two constructors:
\begin{haskell}
data FreeA f x where
DoneA :: x -> FreeA f x
MoreA :: ((a, b) -> x) -> f a -> FreeA f b -> FreeA f x
\end{haskell}
I have inlined the definition of Day convolution:
\begin{haskell}
data Day f g x where
Day :: ((a, b) -> x) -> f a -> g b -> Day f g x
\end{haskell}
The easiest way to show that \hask{FreeA f} is an applicative functor is to go through \hask{Monoidal}:
\begin{haskell}
class Monoidal f where
unit :: f ()
(>*<) :: f a -> f b -> f (a, b)
\end{haskell}
Since \hask{FreeA f} is a generalization of a list, the \hask{Monoidal} instance for free applicative generalizes the idea of list concatenation. We do the pattern matching on the first list, resulting in two cases.
In the first case, instead of an empty list we have \hask{DoneA x}. Prepending it to the second argument doesn't change the length of the list, but it modifies the type of the values stored in it. It pairs each of them with \hask{x}:
\begin{haskell}
(DoneA x) >*< fry = fmap (x,) fry
\end{haskell}
The second case is a ``list'' whose head \hask{fa} is a functorful of \hask{a}'s, and the tail \hask{frb} is of the type \hask{FreeA f b}. The two are glued using a function \hask{abx :: (a, b) -> x}.
\begin{haskell}
(MoreA abx fa frb) >*< fry = MoreA (reassoc abx) fa (frb >*< fry)
\end{haskell}
To produce the result, we concatenate the two tails using the recursive call to \hask{>*<} and prepend \hask{fa} to it. To glue this head to the new tail we have to provide a function that re-associates the pairs:
\begin{haskell}
reassoc :: ((a, b)-> x) -> (a, (b, y)) -> (x, y)
reassoc abx (a, (b, y)) = (abx (a, b), y)
\end{haskell}
The complete instance is thus:
\begin{haskell}
instance Functor f => Monoidal (FreeA f) where
unit = DoneA ()
(DoneA x) >*< fry = fmap (x,) fry
(MoreA abx fa frb) >*< fry = MoreA (reassoc abx) fa (frb >*< fry)
\end{haskell}
Once we have the \hask{Monoidal} instance, it's straightforward to produce the \hask{Applicative} instance:
\begin{haskell}
instance Functor f => Applicative (FreeA f) where
pure a = DoneA a
ff <*> fx = fmap app (ff >*< fx)
app :: (a -> b, a) -> b
app (f, a) = f a
\end{haskell}
\begin{exercise}
Define the \hask{Functor} instance for the free applicative.
\end{exercise}
\section{The Bicategory of Profunctors}
Since we know how to compose profunctors using coends, the question arises: is there a category in which they serve as morphisms? The answer is yes, as long as we relax the rules a bit. The problem is that the categorical laws for profunctor composition are nor satisfied ``on the nose,'' but only up to isomorphism.
For instance, we can try to show associativity of profunctor composition. We start with:
\[ ((P \diamond Q) \diamond R) \langle s, t \rangle = \int^b \left( \int^a P \langle s, a \rangle \times Q \langle a, b \rangle \right) \times R \langle b, t \rangle \]
and, after a few transformations, arrive at:
\[ (P \diamond (Q \diamond R)) \langle s, t \rangle = \int^a P \langle s, a \rangle \times \left( \int^b Q \langle a, b \rangle \times R \langle b, t \rangle \right) \]
We use the associativity of the product and the fact that we can switch the order of coends using the Fubini theorem. Both are true only up to isomorphism. We don't get associativity ``on the nose.''
The identity profunctor turns out to be the hom-functor, which can be written symbolically as $\mathcal{C}(-, =)$, with placeholders for both arguments. For instance:
\[ \left( \mathcal{C}(-, =) \diamond P \right) \langle s, t \rangle = \int^a \mathcal{C}(s, a) \times P \langle a, t \rangle \cong P \langle s, t \rangle \]
This is the consequence of the (contravariant) ninja co-Yoneda lemma, which is also an isomorphism, not an equality.
A category in which categorical laws are satisfied up to isomorphism is called a \index{bicategory}bicategory. Notice that such a category must be equipped with 2-cells---morphisms between morphisms, which we've already seen in the definition of a 2-category. We need those in order to be able to define isomorphisms between 1-cells.
A bicategory $\mathbf{Prof}$ has (small) categories as objects, profunctors as 1-cells, and natural transformations as 2-cells.
Since profunctors are functors $\mathcal{C}^{op} \times \mathcal{D} \to \mathbf{Set}$, the standard definition of natural transformations between them applies. It's a family of functions parameterized by objects of $\mathcal{C}^{op} \times \mathcal{D}$, which are themselves pairs of objects.
The naturality condition for a transformation $\alpha_{\langle a, b \rangle}$ between two profunctors $P$ and $Q$ takes the form:
\[
\begin{tikzcd}
&P \langle a, b \rangle
\arrow[ld, "{\alpha_{\langle a, b \rangle}}"']
\arrow[rd, "{P \langle f, g \rangle}"]
\\
Q \langle a, b \rangle
\arrow[dr, "{Q \langle f, g \rangle}"']
&&P \langle s, t \rangle
\arrow[dl, "{\alpha_{\langle s, t \rangle}}"]
\\
& Q \langle s, t \rangle
\end{tikzcd}
\]
for every pair of arrows:
\[ \langle f \colon s \to a, g \colon b \to t \rangle \]
\subsection{Monads in a bicategory}
We've seen before that categories, functors, and natural transformations form a 2-category $\Cat{Cat}$. Let's focus on one object, a category $\cat C$, that is a 0-cell in $\Cat{Cat}$. The 1-cells that start and end at this object form a regular category, in this case it's the functor category $[\cat C, \cat C]$. The objects in this category are endo-1-cells of the outer 2-category $\Cat{Cat}$. The arrows between them are the 2-cells of the outer 2-category.
This endo-one-cell category is automatically equipped with monoidal structure. We simply define the tensor product as the composition of 1-cells---all 1-cells with the same source and target compose. The monoidal unit object is the identity 1-cell, $I$. In $[\cat C, \cat C]$ this product is the composition of endofunctors and the unit is the identity functor.
If we now focus our attention on just one endo-1-cell $F$, we can ``square'' it, that is use the monoidal product to multiply it by itself. In other words, use the 1-cell composition to create $F \circ F$. We say that $F$ is a monad if we can find 2-cells:
\[ \mu \colon F \circ F \to F \]
\[ \eta \colon I \to F \]
that behave like multiplication and unit, that is they make the associativity and unit diagrams commute.
\[
\begin{tikzpicture}
\node [] (star) {$\cat C$} ;
\path[->,draw] (star) to [in=45,out=135, loop,distance=2cm] node[ below] {$I$} (star);
\path[->,draw] (star) to [in=40,out=140, loop,distance=4cm] node[above] {$F$} (star);
\path[->,draw] (star) to [ in=35,out=145, loop,distance=7cm] node[auto] {$F \circ F$} (star);
\end{tikzpicture}
\]
In fact a monad can be defined in an arbitrary bicategory, not just the 2-category $\Cat{Cat}$.
\subsection{Prearrows as monads in $\Cat{Prof}$}
Since $\Cat{Prof}$ is a bicategory, we can define a monad in it. It is an endo-profunctor (a 1-cell):
\[ P \colon \cat C^{op} \times \cat C \to \Set \]
equipped with two natural transformations (2-cells):
\[ \mu \colon P \diamond P \to P \]
\[ \eta \colon \cat C(-, =) \to P \]
that satisfy the associativity and unit conditions.
Let's look at these natural transformations as elements of ends. For instance:
\[ \mu \in \int_{\langle a, b \rangle} \Set \big( \int^x P \langle a, x \rangle \times P \langle x, b \rangle, P\langle a, b \rangle \big) \]
By co-continuity, this is equivalent to:
\[ \int_{\langle a, b \rangle, x} \Set \big(P \langle a, x \rangle \times P \langle x, b \rangle, P\langle a, b \rangle \big) \]
Similarly, the unit natural transformation is:
\[ \eta \in \int_{\langle a, b \rangle} \Set (\cat C(a, b), P\langle a, b \rangle) \]
In Haskell, such profunctor monads are called pre-arrows:
\begin{haskell}
class Profunctor p => PreArrow p where
(>>>) :: p a x -> p x b -> p a b
arr :: (a -> b) -> p a b
\end{haskell}
An \index{\hask{Arrow}}\hask{Arrow} is a \hask{PreArrow} that is also a Tambara module. We'll talk about Tambara modules in the next chapter.
\section{Existential Lens}
The first rule of category-theory club is that you don't talk about the internals of objects.
The second rule of category-theory club is that, if you have to talk about the internals of objects, use arrows only.
\subsection{Existential lens in Haskell}
What does it mean for an object to be a composite---to have parts? At the very minimum, you should be able to retrieve a part of such an object. Even better if you can replace that part with a new one. This pretty much defines a lens:
\begin{haskell}
get :: s -> a
set :: s -> a -> s
\end{haskell}
Here, \hask{get} extracts the part \hask{a} from the whole \hask{s}, and \hask{set} replaces that part with a new \hask{a}. Lens laws help to reinforce this picture. And it's all done in terms of arrows.
Another way of describing a composite object is to say that it can be split into a focus and a residue. The trick is that, although we want to know what type the focus is, we don't care about the type of the residue. All we need to know about the residue is that it can be combined with the focus to recreate the whole object.
In Haskell, we would express this idea using an \index{existential lens}existential type:
\begin{haskell}
data LensE s a where
LensE :: (s -> (c, a), (c, a) -> s) -> LensE s a
\end{haskell}
This tells us that there exists some unspecified type \hask{c}, such that \hask{s} can be split into, and reconstructed from, a product \hask{(c, a)}.
\[
\begin{tikzpicture}
\filldraw[fill=gray!50, draw=white] (0, 0) circle (1.2);
\node at (0, -0.9) {$s$};
\end{tikzpicture}
\hspace{20pt}
\begin{tikzpicture}
\filldraw[fill=blue!50!green!20, draw=white] (0, 0) circle (1.2);
\filldraw[fill=orange!30, draw=white] (0, 0) circle (0.6);
\node at (0, 0) {$a$};
\node at (0, -0.9) {$c$};
\end{tikzpicture}
\]
The \hask{get}/\hask{set} version of the lens can be derived from this existential form.
\begin{haskell}
toGet :: LensE s a -> (s -> a)
toGet (LensE (l, r)) = snd . l
toSet :: LensE s a -> (s -> a -> s)
toSet (LensE (l, r)) s a = r (fst (l s), a)
\end{haskell}
Notice that we don't need to know anything about the type of the residue. We take advantage of the fact that the existential lens contains both the producer and the consumer of \hask{c} and we're just mediating between the two.
It's impossible to extract a ``naked'' residue, as witnessed by the fact that the following code doesn't compile:
\begin{haskell}
getResidue :: LensE s a -> c
getResidue (LensE (l, r)) = fst . l
\end{haskell}
\subsection{Existential lens in category theory}
We can easily translate the new definition of the lens to category theory by expressing the existential type as a coend:
\[ \int^{c} \mathcal{C}(s, c \times a) \times \mathcal{C}(c \times a, s) \]
In fact, we can generalize it to a type-changing lens, in which the focus $a$ can be replaced with a new focus of a different type $b$. Replacing $a$ with $b$ will produce a new composite object $t$:
\[
\begin{tikzpicture}
\filldraw[fill=blue!50!green!20, draw=white] (0, 0) circle (1.2);
\filldraw[fill=orange!30, draw=white] (0, 0) circle (0.6);