-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathrss.xml
2597 lines (2463 loc) · 466 KB
/
rss.xml
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
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>The Life Monadic</title>
<link>https://duplode.github.io</link>
<description><![CDATA[Haskell amusements]]></description>
<atom:link href="https://duplode.github.io/rss.xml" rel="self"
type="application/rss+xml" />
<lastBuildDate>Mon, 07 Feb 2022 19:55:00 UT</lastBuildDate>
<item>
<title>Every Distributive is Representable</title>
<link>https://duplode.github.io/posts/every-distributive-is-representable.html</link>
<description><![CDATA[
<p>“Every <code>Distributive</code> <code>Functor</code> is actually <code>Representable</code>”, as the documentation for <a href="https://hackage.haskell.org/package/adjunctions-4.4/docs/Data-Functor-Rep.html"><code>Representable</code></a> tells us straight away, and yet it is far from obvious why that should be the case. At first glance, <a href="https://hackage.haskell.org/package/distributive-0.6.2.1/docs/Data-Distributive.html"><code>Distributive</code></a>, the dual to <code>Traversable</code>, appears to have little if anything to do with <code>Representable</code>, the class for functors isomorphic to functions. The goal of this post is making this connection explicit. In the process, we will tease out a fair amount of information about the two classes, and also contemplate what makes it tricky to fully bridge the gap to <code>Representable</code>.</p>
<div>
</div>
<!--more-->
<h2 id="the-basic-facts">The basic facts</h2>
<p>Over the course of this post, the focus will alternate between <code>Distributive</code> and <code>Representable</code>. In this first section, we will review the basic definitions and laws upon which we will build. Following that, we will work on both ends, aiming at making the classes meet in the middle.</p>
<h3 id="distributive">Distributive</h3>
<p>Let’s begin by jotting down a few basic facts about <code>Distributive</code>. Here is a minimalistic definition of the class:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Functor</span> g <span class="ot">=></span> <span class="dt">Distributive</span> g <span class="kw">where</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot"> distribute ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f (g a) <span class="ot">-></span> g (f a)</span></code></pre></div>
<p>(In what follows, when used as a placeholder name for a functor, <code>g</code> will always stand for a distributive or representable functor, while <code>f</code> will typically stand for the other functor involved in <code>distribute</code>.)</p>
<p><code>distribute</code> is dual to <code>sequenceA</code>; accordingly, we will adopt the duals of <a href="https://hackage.haskell.org/package/base-4.16.0.0/docs/Data-Traversable.html#g:20">the <code>Traversable</code> laws</a>: <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<ul>
<li><p>Identity:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> runIdentity <span class="op">.</span> distribute <span class="ot">=</span> runIdentity</span></code></pre></div></li>
<li><p>Composition:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> getCompose <span class="op">.</span> distribute</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> distribute <span class="op">.</span> <span class="fu">fmap</span> distribute <span class="op">.</span> getCompose</span></code></pre></div></li>
<li><p>Naturality (ensured by parametricity):</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- For any natural transformation t</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- t :: (Functor f1, Functor f2) => forall x. f1 x -> f2 x</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> t <span class="op">.</span> distribute <span class="ot">=</span> distribute <span class="op">.</span> t</span></code></pre></div>
<p>This naturality law is stronger than its <code>Traversable</code> counterpart. The <code>Applicative</code> constraint in <code>sequenceA</code> means only natural transformations between applicative functors that preserve <code>pure</code> and <code>(<*>)</code> are preserved by <code>distribute</code>. In contrast, <code>distribute</code> is oblivious to any specifics of <code>f1</code> and <code>f2</code> functor, and so any natural transformation will do.</p></li>
</ul>
<p>Homogeneous pairs are one example of a distributive functor:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Duo</span> a <span class="ot">=</span> <span class="dt">Duo</span> a a</span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Ord</span>, <span class="dt">Show</span>, <span class="dt">Functor</span>, <span class="dt">Foldable</span>, <span class="dt">Traversable</span>)</span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>fstDuo,<span class="ot"> sndDuo ::</span> <span class="dt">Duo</span> a <span class="ot">-></span> a</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a>fstDuo (<span class="dt">Duo</span> x _) <span class="ot">=</span> x</span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a>sndDuo (<span class="dt">Duo</span> _ y) <span class="ot">=</span> y</span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Distributive</span> <span class="dt">Duo</span> <span class="kw">where</span></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a> distribute m <span class="ot">=</span> <span class="dt">Duo</span> (fstDuo <span class="op"><$></span> m) (sndDuo <span class="op"><$></span> m)</span></code></pre></div>
<p><code>Duo</code> will be used in this post as a running example whenever a concrete illustration of <code>Distributive</code> and adjacent classes is called for. For the moment, here is a simple demonstration of <code>distribute @Duo</code> in action. It illustrates the zip-like flavour of <code>distribute</code>, which is shared by the closely related <code>collect</code> and <code>cotraverse</code> from <code>Data.Distributive</code>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">names ::</span> [<span class="dt">Duo</span> <span class="dt">String</span>]</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>names <span class="ot">=</span></span>
<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> [ <span class="dt">Duo</span> <span class="st">"Alex"</span> <span class="st">"Lifeson"</span></span>
<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> , <span class="dt">Duo</span> <span class="st">"Geddy"</span> <span class="st">"Lee"</span></span>
<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a> , <span class="dt">Duo</span> <span class="st">"Neil"</span> <span class="st">"Peart"</span></span>
<span id="cb6-6"><a href="#cb6-6" aria-hidden="true" tabindex="-1"></a> ]</span></code></pre></div>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a>ghci<span class="op">></span> distribute names</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Duo</span> [<span class="st">"Alex"</span>,<span class="st">"Geddy"</span>,<span class="st">"Neil"</span>] [<span class="st">"Lifeson"</span>,<span class="st">"Lee"</span>,<span class="st">"Peart"</span>]</span></code></pre></div>
<p>The function functor is a very important example of <code>Distributive</code>. Consider the following combinator:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">flap ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f (r <span class="ot">-></span> a) <span class="ot">-></span> r <span class="ot">-></span> f a</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>flap m <span class="ot">=</span> \r <span class="ot">-></span> (\f <span class="ot">-></span> f r) <span class="op"><$></span> m</span></code></pre></div>
<p>It changes a <code>f (r -> a)</code> functorial value into a <code>r -> f a</code> function, which feeds its argument to all of the available <code>r -> a</code> functions. <code>flap</code> is a lawful implementation of <code>distribute</code>:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Distributive</span> ((<span class="ot">-></span>) r) <span class="kw">where</span></span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a> distribute <span class="ot">=</span> flap</span></code></pre></div>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a>ghci<span class="op">></span> distribute [(<span class="op">*</span><span class="dv">3</span>), (<span class="op">+</span><span class="dv">7</span>), (<span class="op">^</span><span class="dv">2</span>)] <span class="dv">8</span></span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>[<span class="dv">24</span>,<span class="dv">15</span>,<span class="dv">64</span>]</span></code></pre></div>
<p><code>flap</code> will be used in this post as a synonym for <code>distribute @((->) _)</code> whenever convenient, or necessary to avoid circularity. <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></p>
<h3 id="representable">Representable</h3>
<p>As for <code>Representable</code>, for our immediate purposes it suffices to characterise it as a class for functors isomorphic to functions:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Functor</span> g <span class="ot">=></span> <span class="dt">Representable</span> g <span class="kw">where</span></span>
<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">type</span> <span class="dt">Rep</span> g</span>
<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="ot"> tabulate ::</span> (<span class="dt">Rep</span> g <span class="ot">-></span> a) <span class="ot">-></span> g a</span>
<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a><span class="ot"> index ::</span> g a <span class="ot">-></span> <span class="dt">Rep</span> g <span class="ot">-></span> a</span></code></pre></div>
<p>Here, <code>Rep g</code> is some concrete type such that <code>tabulate</code> and <code>index</code> witness an isomorphism between <code>Rep g -> a</code> and <code>g a</code>. Accordingly, the laws are:</p>
<ul>
<li><p>Home direction (from <code>g a</code> and back):</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> <span class="fu">index</span> <span class="ot">=</span> <span class="fu">id</span></span></code></pre></div></li>
<li><p>Away direction (to <code>g a</code> and back):</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span> <span class="op">.</span> tabulate <span class="ot">=</span> <span class="fu">id</span></span></code></pre></div></li>
</ul>
<p><code>Duo</code> can be given a <code>Representable</code> instance: pick <code>Bool</code> (or any other type with two inhabitants) as <code>Rep g</code>, and associate each possible value with a component of the pair:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Representable</span> <span class="dt">Duo</span> <span class="kw">where</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">type</span> <span class="dt">Rep</span> <span class="dt">Duo</span> <span class="ot">=</span> <span class="dt">Bool</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> tabulate f <span class="ot">=</span> <span class="dt">Duo</span> (f <span class="dt">False</span>) (f <span class="dt">True</span>)</span>
<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">index</span> (<span class="dt">Duo</span> x y) <span class="ot">=</span> \<span class="kw">case</span></span>
<span id="cb14-5"><a href="#cb14-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">False</span> <span class="ot">-></span> x</span>
<span id="cb14-6"><a href="#cb14-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">True</span> <span class="ot">-></span> y</span></code></pre></div>
<p>In order to treat the two classes in an even-handed way, I have opted to leave out the <code>Distributive g => Representable g</code> relationship that exists in the <code>Data.Functor.Rep</code> version of <code>Representable</code> . In any case, every representable is indeed distributive, with a default definition of <code>distribute</code> which uses the isomorphism to delegate to <code>flap</code> (that is, <code>distribute</code> for functions):</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">distributeRep ::</span> (<span class="dt">Representable</span> g, <span class="dt">Functor</span> f) <span class="ot">=></span> f (g a) <span class="ot">-></span> g (f a)</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>distributeRep <span class="ot">=</span> tabulate <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span></code></pre></div>
<p>The lawfulness of <code>distributeRep</code> follows from the lawfulness of <code>flap</code>. <a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<p>Our ultimate aim here is to go the other way around, from <code>Distributive</code> to <code>Representable</code>.</p>
<h2 id="no-need-to-choose">No need to choose</h2>
<p>If we are to start from <code>Distributive</code>, though, there is a pretty fundamental difficulty: setting up a <code>Representable g</code> instance requires picking a suitable <code>Rep g</code>, and there is nothing in <code>Distributive</code> that could possibly correspond to such a choice. That being so, we will spend some more time contemplating <code>Representable</code>, looking for a way to somehow obviate the need for specifying <code>Rep g</code>.</p>
<h3 id="askrep">askRep</h3>
<p>Let’s have another look at the type of <code>tabulate</code>:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ot">tabulate ::</span> <span class="dt">Representable</span> g <span class="ot">=></span> (<span class="dt">Rep</span> g <span class="ot">-></span> a) <span class="ot">-></span> g a</span></code></pre></div>
<p><code>tabulate</code> is a natural transformation from the function functor <code>((->) (Rep g)</code> to <code>g</code>. Now, all natural transformations from a function functor have the form: <a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- For some type R, functor G, and any</span></span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="ot">t ::</span> <span class="kw">forall</span> x<span class="op">.</span> (<span class="dt">R</span> <span class="ot">-></span> x) <span class="ot">-></span> <span class="dt">G</span> x</span>
<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- There is a</span></span>
<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a><span class="ot">w ::</span> <span class="dt">G</span> <span class="dt">R</span></span>
<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Such that</span></span>
<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a>t f <span class="ot">=</span> f <span class="op"><$></span> w</span>
<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a>w <span class="ot">=</span> t <span class="fu">id</span></span></code></pre></div>
<p>In words, the natural transformation must amount to mapping the function over some functorial value. In our case, <code>t</code> is <code>tabulate</code>; as for <code>w</code>, we will call it <code>askRep</code>, which is <a href="https://hackage.haskell.org/package/adjunctions-4.4/docs/src/Data-Functor-Rep.html#askRep">the name it goes by in <code>Data.Functor.Rep</code></a>. <a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a>. That being so, we have:</p>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="ot">askRep ::</span> <span class="dt">Representable</span> g <span class="ot">=></span> g (<span class="dt">Rep</span> g)</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>askRep <span class="ot">=</span> tabulate <span class="fu">id</span></span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a>tabulate f <span class="ot">=</span> f <span class="op"><$></span> askRep</span></code></pre></div>
<p>The <code>Representable</code> laws can be recast in terms of <code>askRep</code> and <code>index</code>. Here is the home direction of the isomorphism:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> <span class="fu">index</span> <span class="ot">=</span> <span class="fu">id</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>tabulate (<span class="fu">index</span> u) <span class="ot">=</span> u</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span> u <span class="op"><$></span> askRep <span class="ot">=</span> u</span></code></pre></div>
<p>That is, we can reconstruct any <code>u :: g a</code> by taking <code>askRep</code> and replacing every <code>Rep g</code> provided by it with the <code>a</code> value that applying <code>index u</code> on it gives us.</p>
<p>It is worth noting that <code>index u <$> askRep = u</code> also tells us that for any <code>u :: g a</code> there is a function (namely, <code>index u</code>) which will change <code>askRep</code> into <code>u</code> through <code>fmap</code>. That largely corresponds to the intuition that a representable functor must have a single shape.</p>
<p>The away direction of the isomorphism becomes:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span> <span class="op">.</span> tabulate <span class="ot">=</span> <span class="fu">id</span></span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span> (f <span class="op"><$></span> askRep) <span class="ot">=</span> f</span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- index is a natural transformation</span></span>
<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a>f <span class="op"><$></span> <span class="fu">index</span> askRep <span class="ot">=</span> f</span>
<span id="cb21-5"><a href="#cb21-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- fmap @((->) _) = (.)</span></span>
<span id="cb21-6"><a href="#cb21-6" aria-hidden="true" tabindex="-1"></a>f <span class="op">.</span> <span class="fu">index</span> askRep <span class="ot">=</span> f</span>
<span id="cb21-7"><a href="#cb21-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- In particular, suppose f = id</span></span>
<span id="cb21-8"><a href="#cb21-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- (note that this step is reversible)</span></span>
<span id="cb21-9"><a href="#cb21-9" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span> askRep <span class="ot">=</span> <span class="fu">id</span></span></code></pre></div>
<p>Intuitively, if we think of <code>Rep g</code> values as corresponding to positions in the <code>g</code> shape that can be queried through <code>index</code>, <code>index askRep = id</code> tells us that each and every <code>Rep g</code> will be found in <code>askRep</code> occupying the position it corresponds to. For example, with the <code>Representable</code> instance from the previous section, <code>askRep @Duo</code> looks like this:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a>ghci<span class="op">></span> askRep <span class="op">@</span><span class="dt">Duo</span></span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Duo</span> <span class="dt">False</span> <span class="dt">True</span></span></code></pre></div>
<p>Lastly, we can also express <code>distributeRep</code> in terms of <code>askRep</code>:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>distributeRep m</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>tabulate (flap (<span class="fu">index</span> <span class="op"><$></span> m))</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a>flap (<span class="fu">index</span> <span class="op"><$></span> m) <span class="op"><$></span> askRep</span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a>(\r <span class="ot">-></span> (\f <span class="ot">-></span> f r) <span class="op"><$></span> (<span class="fu">index</span> <span class="op"><$></span> m)) <span class="op"><$></span> askRep</span>
<span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a>(\r <span class="ot">-></span> (\u <span class="ot">-></span> <span class="fu">index</span> u r) <span class="op"><$></span> m) <span class="op"><$></span> askRep</span>
<span id="cb23-6"><a href="#cb23-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb23-7"><a href="#cb23-7" aria-hidden="true" tabindex="-1"></a>distributeRep m <span class="ot">=</span> (\r <span class="ot">-></span> (\u <span class="ot">-></span> <span class="fu">index</span> u r) <span class="op"><$></span> m) <span class="op"><$></span> askRep</span></code></pre></div>
<p>That is, replace every <code>Rep g</code> in <code>askRep</code> with the result of using it to <code>index</code> every <code>g a</code> in <code>m</code>.</p>
<h3 id="extracting-and-revealing">Extracting and revealing</h3>
<p>Now let’s direct our attention to <code>index</code>:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="fu">index</span><span class="ot"> ::</span> <span class="dt">Representable</span> g <span class="ot">=></span> g a <span class="ot">-></span> <span class="dt">Rep</span> g <span class="ot">-></span> a</span></code></pre></div>
<p>Flipping <code>index</code> gives us:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ot">fromRep ::</span> <span class="dt">Representable</span> g <span class="ot">=></span> <span class="dt">Rep</span> g <span class="ot">-></span> g a <span class="ot">-></span> a</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>fromRep r <span class="ot">=</span> \u <span class="ot">-></span> <span class="fu">index</span> u r</span></code></pre></div>
<p><code>fromRep</code> converts a <code>Rep g</code> into what I will call a <em>polymorphic extractor</em>, of type <code>forall a. g a -> a</code>, which gives us <code>a</code> out of <code>g a</code>. The existence of <code>fromRep</code> is quite suggestive. Since <code>forall a. g a -> a</code> doesn’t use <code>Rep g</code>, finding an inverse to <code>fromRep</code>, and thus showing those two types are isomorphic, might give us a way to work with <code>Representable</code> without relying on <code>Rep g</code>.</p>
<p>How might we go about converting a polymorphic extractor into a <code>Rep g</code> value? To do it in a non-trivial way , we will need a <code>g (Rep g)</code> source of <code>Rep g</code> on which we can use the extractor. Considering the discussion in the previous subsection, <code>askRep</code> looks like a reasonable option:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="ot">toRep ::</span> <span class="dt">Representable</span> g <span class="ot">=></span> (<span class="kw">forall</span> x<span class="op">.</span> g x <span class="ot">-></span> x) <span class="ot">-></span> <span class="dt">Rep</span> g</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>toRep p <span class="ot">=</span> p askRep</span></code></pre></div>
<p>Now let’s check if <code>fromRep</code> and <code>toRep</code> are indeed inverses, beginning with the <code>toRep . fromRep</code> direction:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>toRep <span class="op">.</span> fromRep</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p askRep) <span class="op">.</span> (\r <span class="ot">-></span> \u <span class="ot">-></span> <span class="fu">index</span> u r)</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>\r <span class="ot">-></span> (\u <span class="ot">-></span> <span class="fu">index</span> u r) askRep</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>\r <span class="ot">-></span> <span class="fu">index</span> askRep r</span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- index askRep = id</span></span>
<span id="cb27-6"><a href="#cb27-6" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span></span></code></pre></div>
<p>We can proceed similarly with <code>fromRep . toRep</code>:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a>fromRep <span class="op">.</span> toRep</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>(\r <span class="ot">-></span> \u <span class="ot">-></span> <span class="fu">index</span> u r) <span class="op">.</span> (\p <span class="ot">-></span> p askRep)</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a>\p <span class="ot">-></span> \u <span class="ot">-></span> <span class="fu">index</span> u (p askRep)</span></code></pre></div>
<p>To simplify this further, we can note that a polymorphic extractor <code>forall x. g x -> x</code> amounts to natural transformation from <code>g</code> to <code>Identity</code>. That being so, we have, for any extractor <code>p</code> and any <code>f</code>:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a>f <span class="op">.</span> p <span class="ot">=</span> p <span class="op">.</span> <span class="fu">fmap</span> f</span></code></pre></div>
<p>The above is the usual naturality property, <code>fmap f . p = p . fmap f</code>, except that, to account for the omission of the <code>Identity</code> newtype boilerplate, <code>fmap @Identity</code> has been replaced on the left-hand side by plain function application. We can now carry on:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>\p <span class="ot">-></span> \u <span class="ot">-></span> <span class="fu">index</span> u (p askRep)</span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>\p <span class="ot">-></span> \u <span class="ot">-></span> p (<span class="fu">index</span> u <span class="op"><$></span> askRep)</span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- index u <$> askRep = u</span></span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>\p <span class="ot">-></span> \u <span class="ot">-></span> p u</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="fu">id</span></span></code></pre></div>
<p>And there it is: for any <code>Representable</code>, <code>Rep g</code> must be isomorphic to <code>forall x. g x -> x</code>. That being so, we can use <code>forall x. g x -> x</code> as a default <code>Rep g</code> that can be specified in terms of <code>g</code> alone. The change of perspective can be made clearer by setting up an alternative class:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> <span class="dt">Pos</span> g <span class="ot">=</span> <span class="kw">forall</span> x<span class="op">.</span> g x <span class="ot">-></span> x</span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a><span class="ot">elide ::</span> g a <span class="ot">-></span> <span class="dt">Pos</span> g <span class="ot">-></span> a</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>elide u <span class="ot">=</span> \p <span class="ot">-></span> p u</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a><span class="kw">class</span> <span class="dt">Functor</span> g <span class="ot">=></span> <span class="dt">Revealable</span> g <span class="kw">where</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a><span class="ot"> reveal ::</span> (<span class="dt">Pos</span> g <span class="ot">-></span> a) <span class="ot">-></span> g a</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a><span class="ot"> chart ::</span> g (<span class="dt">Pos</span> g)</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a> reveal e <span class="ot">=</span> e <span class="op"><$></span> chart</span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a> chart <span class="ot">=</span> reveal <span class="fu">id</span></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a> <span class="ot">{-# MINIMAL reveal | chart #-}</span></span></code></pre></div>
<p>Both the arrangement of those definitions and my idiosyncratic choice of names call for some explanation:</p>
<ul>
<li><p><code>Pos g</code> is a synonym for the type of polymorphic extractors. The name <code>Pos</code> is short for “position”, and is meant to allude to the intuition that an extractor picks a value from some specific position in a <code>g</code>-shaped structure.</p></li>
<li><p><code>elide</code> corresponds to <code>index</code>, defined in such a way that <code>fromRep = id</code>. Since all it does is applying a <code>Pos g</code> extractor, on its own it doesn’t require any constraints on <code>g</code>. The choice of name is motivated by how <code>elide</code> hides the <code>g</code> shape, in that that the only information about <code>u :: g a</code> that can be recovered from <code>elide u</code> are the <code>a</code> values that a <code>Pos g</code> extractor can reach.</p></li>
<li><p><code>reveal</code>, in turn, corresponds to <code>tabulate</code>, and is the inverse of <code>elide</code>. If <code>g</code> is <code>Representable</code>, the <code>g</code> shape can be reconstituted with no additional information, and so it is possible to undo the hiding performed by <code>elide</code>.</p></li>
<li><p><code>chart</code> corresponds to <code>askRep</code>, with it and <code>reveal</code> being interdefinable. In particular, <code>chart</code> can be used to reveal the <code>g a</code> that corresponds to a <code>Pos g -> a</code> function by providing the means to reach every position in the <code>g</code> shape. <a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a></p></li>
</ul>
<p>Here is the <code>Duo</code> instance of <code>Revealable</code>. Note how each position in <code>chart</code> holds its own extractor:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Revealable</span> <span class="dt">Duo</span> <span class="kw">where</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a> reveal e <span class="ot">=</span> <span class="dt">Duo</span> (e fstDuo) (e sndDuo)</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a> chart <span class="ot">=</span> <span class="dt">Duo</span> fstDuo sndDuo</span></code></pre></div>
<p><code>distribute</code> can be implemented for <code>Revealable</code> in a way completely analogous to how it was done for <code>Representable</code>:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">distributeRev ::</span> (<span class="dt">Revealable</span> g, <span class="dt">Functor</span> f) <span class="ot">=></span> f (g a) <span class="ot">-></span> g (f a)</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>distributeRev <span class="ot">=</span> reveal <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> elide</span></code></pre></div>
<p>Or, in terms of <code>chart</code>:</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a>distributeRev m <span class="ot">=</span> (\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> chart</span></code></pre></div>
<p>That is, <code>distributeRev m</code> amounts to mapping every extractor in <code>chart</code> over <code>m</code>.</p>
<p>As for the laws, just like we were able to choose between expressing the <code>Representable</code> isomorphism directly, via <code>tabulate</code>, or indirectly via <code>askRep</code>, here we can use either <code>reveal</code> or <code>chart</code>:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a>reveal <span class="op">.</span> elide <span class="ot">=</span> <span class="fu">id</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- Or, equivalently</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a>elide u <span class="op"><$></span> chart <span class="ot">=</span> u</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a>elide <span class="op">.</span> reveal <span class="ot">=</span> <span class="fu">id</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- Or, equivalently</span></span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a>p chart <span class="ot">=</span> p</span></code></pre></div>
<p>With <code>Revealable</code>, though, we can streamline things by showing <code>p chart = p</code> follows from <code>elide u <$> chart = u</code>. The proof relies on the naturality of the polymorphic extractors:</p>
<div class="sourceCode" id="cb36"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb36-1"><a href="#cb36-1" aria-hidden="true" tabindex="-1"></a>elide u <span class="op"><$></span> chart <span class="ot">=</span> u</span>
<span id="cb36-2"><a href="#cb36-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- Apply some p :: Pos g to both sides</span></span>
<span id="cb36-3"><a href="#cb36-3" aria-hidden="true" tabindex="-1"></a>p (elide u <span class="op"><$></span> chart) <span class="ot">=</span> p u</span>
<span id="cb36-4"><a href="#cb36-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- p is natural</span></span>
<span id="cb36-5"><a href="#cb36-5" aria-hidden="true" tabindex="-1"></a>elide u (p chart) <span class="ot">=</span> p u</span>
<span id="cb36-6"><a href="#cb36-6" aria-hidden="true" tabindex="-1"></a><span class="co">-- elide u p = p u</span></span>
<span id="cb36-7"><a href="#cb36-7" aria-hidden="true" tabindex="-1"></a>(p chart) u <span class="ot">=</span> p u</span>
<span id="cb36-8"><a href="#cb36-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- u is arbitrary</span></span>
<span id="cb36-9"><a href="#cb36-9" aria-hidden="true" tabindex="-1"></a>p chart <span class="ot">=</span> p</span></code></pre></div>
<p>That being so, <code>elide u <$> chart = u</code> is the only law we need to characterise <code>Revealable</code>. Since <code>elide</code> does not depend on the <code>Revealable</code> instance, we might as well inline its definition, which leaves us with:</p>
<div class="sourceCode" id="cb37"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) <span class="op"><$></span> chart <span class="ot">=</span> u</span></code></pre></div>
<p>I suggest calling it the <em>law of extractors</em>: it tells us that the extractors provided by <code>chart</code> suffice to reconstitute an arbitrary <code>g a</code> value.</p>
<h2 id="revisiting-distributive">Revisiting Distributive</h2>
<p>In <code>Revealable</code>, we have a class equivalent to <code>Representable</code> which doesn’t rely on the <code>Rep</code> type family. That makes it feasible to continue our investigation by attempting to show that every <code>Distributive</code> functor is <code>Revealable</code>.</p>
<h3 id="natural-wonders">Natural wonders</h3>
<p>Naturality laws and parametricity properties not infrequently have interesting consequences that seem to us as hidden in plain sight. Considering the increased strength of <code>Distributive</code>’s naturality law relative to its <code>Traversable</code> counterpart and the important role naturality properties had in setting up <code>Revealable</code>, resuming our work on <code>Distributive</code> from the naturality law sounds like a reasonable bet:</p>
<div class="sourceCode" id="cb38"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb38-1"><a href="#cb38-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- For any natural transformation t</span></span>
<span id="cb38-2"><a href="#cb38-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- t :: (Functor f1, Functor f2) => forall x. f1 x -> f2 x</span></span>
<span id="cb38-3"><a href="#cb38-3" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> t <span class="op">.</span> distribute <span class="ot">=</span> distribute <span class="op">.</span> t</span></code></pre></div>
<p>In particular, suppose <code>f1</code> is a function functor:</p>
<div class="sourceCode" id="cb39"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- t :: Functor f => forall x. (r -> x) -> f x</span></span>
<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a>t <span class="op"><$></span> distribute f <span class="ot">=</span> distribute (t f)</span></code></pre></div>
<p>Now, by the same argument used back when we defined <code>askRep</code>, <code>t</code> must have the form:</p>
<div class="sourceCode" id="cb40"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- m :: f r</span></span>
<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a>t f <span class="ot">=</span> f <span class="op"><$></span> m</span></code></pre></div>
<p>Therefore:</p>
<div class="sourceCode" id="cb41"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> distribute f <span class="ot">=</span> distribute (f <span class="op"><$></span> m)</span></code></pre></div>
<p>In particular, suppose <code>f = id</code>. We then end up with an specification of <code>distribute</code> in terms of <code>distribute id</code>:</p>
<div class="sourceCode" id="cb42"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb42-1"><a href="#cb42-1" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> distribute <span class="fu">id</span> <span class="ot">=</span> distribute m</span></code></pre></div>
<p><code>distribute id</code> has the following type:</p>
<div class="sourceCode" id="cb43"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb43-1"><a href="#cb43-1" aria-hidden="true" tabindex="-1"></a>ghci<span class="op">></span> <span class="op">:</span>t distribute <span class="fu">id</span></span>
<span id="cb43-2"><a href="#cb43-2" aria-hidden="true" tabindex="-1"></a>distribute<span class="ot"> id ::</span> <span class="dt">Distributive</span> g <span class="ot">=></span> g (g a <span class="ot">-></span> a)</span></code></pre></div>
<p>This looks a lot like something that holds extractors, and the specification itself mirrors the definition of <code>distributeRev</code> in terms of <code>chart</code>. As a preliminary check, <code>distribute @Duo id</code> holds <code>fstDuo</code> and <code>sndDuo</code> on their respective positions, exactly like <code>chart @Duo</code>:</p>
<div class="sourceCode" id="cb44"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb44-1"><a href="#cb44-1" aria-hidden="true" tabindex="-1"></a>distribute <span class="op">@</span><span class="dt">Duo</span> <span class="fu">id</span></span>
<span id="cb44-2"><a href="#cb44-2" aria-hidden="true" tabindex="-1"></a><span class="dt">Duo</span> (<span class="fu">id</span> <span class="op"><$></span> fstDuo) (<span class="fu">id</span> <span class="op"><$></span> sndDuo)</span>
<span id="cb44-3"><a href="#cb44-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Duo</span> fstDuo sndDuo</span></code></pre></div>
<p>Given the clear resemblance, I will optimistically refer to <code>distribute id</code> as <code>chartDist</code>:</p>
<div class="sourceCode" id="cb45"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb45-1"><a href="#cb45-1" aria-hidden="true" tabindex="-1"></a><span class="ot">chartDist ::</span> <span class="dt">Distributive</span> g <span class="ot">=></span> g (g a <span class="ot">-></span> a)</span>
<span id="cb45-2"><a href="#cb45-2" aria-hidden="true" tabindex="-1"></a>chartDist <span class="ot">=</span> distribute <span class="fu">id</span></span></code></pre></div>
<p>We therefore have:</p>
<div class="sourceCode" id="cb46"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb46-1"><a href="#cb46-1" aria-hidden="true" tabindex="-1"></a>distribute m <span class="ot">=</span> (\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> chartDist</span></code></pre></div>
<p>Now suppose <code>m = Identity u</code> for some <code>u :: g a</code>, and invoke the identity law:</p>
<div class="sourceCode" id="cb47"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb47-1"><a href="#cb47-1" aria-hidden="true" tabindex="-1"></a>distribute (<span class="dt">Identity</span> u) <span class="ot">=</span> (\p <span class="ot">-></span> p <span class="op"><$></span> <span class="dt">Identity</span> u) <span class="op"><$></span> chartDist</span>
<span id="cb47-2"><a href="#cb47-2" aria-hidden="true" tabindex="-1"></a>distribute (<span class="dt">Identity</span> u) <span class="ot">=</span> (\p <span class="ot">-></span> <span class="dt">Identity</span> (p u)) <span class="op"><$></span> chartDist</span>
<span id="cb47-3"><a href="#cb47-3" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op"><$></span> distribute (<span class="dt">Identity</span> u)</span>
<span id="cb47-4"><a href="#cb47-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> runIdentity <span class="op"><$></span> ((\p <span class="ot">-></span><span class="dt">Identity</span> (p u)) <span class="op"><$></span> chartDist)</span>
<span id="cb47-5"><a href="#cb47-5" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op"><$></span> distribute (<span class="dt">Identity</span> u)</span>
<span id="cb47-6"><a href="#cb47-6" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\p <span class="ot">-></span> runIdentity (<span class="dt">Identity</span> (p u))) <span class="op"><$></span> chartDist</span>
<span id="cb47-7"><a href="#cb47-7" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op"><$></span> distribute (<span class="dt">Identity</span> u)</span>
<span id="cb47-8"><a href="#cb47-8" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist</span>
<span id="cb47-9"><a href="#cb47-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- By the identity law</span></span>
<span id="cb47-10"><a href="#cb47-10" aria-hidden="true" tabindex="-1"></a>runIdentity (<span class="dt">Identity</span> u) <span class="ot">=</span> (\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist</span>
<span id="cb47-11"><a href="#cb47-11" aria-hidden="true" tabindex="-1"></a>u <span class="ot">=</span> (\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist</span></code></pre></div>
<p>We therefore have a <code>Distributive</code> version of the law of extractors, with <code>chartDist</code> playing the role of <code>chart</code>. It is also possible to turn things around and obtain the identity law from this law of extractors:</p>
<div class="sourceCode" id="cb48"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb48-1"><a href="#cb48-1" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist <span class="ot">=</span> u</span>
<span id="cb48-2"><a href="#cb48-2" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op">.</span> <span class="dt">Identity</span> <span class="op">.</span> (\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist <span class="ot">=</span> u</span>
<span id="cb48-3"><a href="#cb48-3" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op">.</span> (\p <span class="ot">-></span> <span class="dt">Identity</span> (p u)) <span class="op"><$></span> chartDist <span class="ot">=</span> u</span>
<span id="cb48-4"><a href="#cb48-4" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op">.</span> (\p <span class="ot">-></span> p <span class="op"><$></span> <span class="dt">Identity</span> u) <span class="op"><$></span> chartDist <span class="ot">=</span> u</span>
<span id="cb48-5"><a href="#cb48-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- distribute m = (\p -> p <$> m) <$> chartDist</span></span>
<span id="cb48-6"><a href="#cb48-6" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op"><$></span> distribute (<span class="dt">Identity</span> u) <span class="ot">=</span> u</span>
<span id="cb48-7"><a href="#cb48-7" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="op"><$></span> distribute (<span class="dt">Identity</span> u) <span class="ot">=</span> runIdentity (<span class="dt">Identity</span> u)</span>
<span id="cb48-8"><a href="#cb48-8" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> runIdentity <span class="op">.</span> distribute <span class="ot">=</span> runIdentity</span></code></pre></div>
<p>These are auspicious results. Given that the law of extractors is enough to establish an implementation of <code>chart</code> as lawful, and that there can’t be multiple distinct lawful implementations of <code>distribute</code> <a href="#fn7" class="footnote-ref" id="fnref7" role="doc-noteref"><sup>7</sup></a>, all we need to do is to identify <code>chartDist</code> with <code>chart</code>.</p>
<h3 id="the-roadblock-and-a-detour">The roadblock, and a detour</h3>
<p>Identifying <code>chartDist</code> with <code>chart</code>, however, is not trivial. As similar as <code>chart</code> and <code>chartDist</code> might feel like, their types differ in an insurmountable way:</p>
<div class="sourceCode" id="cb49"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb49-1"><a href="#cb49-1" aria-hidden="true" tabindex="-1"></a>chart <span class="op">@</span><span class="dt">G</span><span class="ot"> ::</span> <span class="dt">G</span> (<span class="kw">forall</span> a<span class="op">.</span> <span class="dt">G</span> a <span class="ot">-></span> a) <span class="co">-- G (Pos G)</span></span>
<span id="cb49-2"><a href="#cb49-2" aria-hidden="true" tabindex="-1"></a>chartDist <span class="op">@</span><span class="dt">G</span><span class="ot"> ::</span> <span class="kw">forall</span> a<span class="op">.</span> <span class="dt">G</span> (<span class="dt">G</span> a <span class="ot">-></span> a)</span></code></pre></div>
<p>In particular:</p>
<ul>
<li><p>The <code>a</code> in <code>forall a. G (G a -> a)</code> can be directly specialised to a concrete choice of <code>a</code>, and, as far as the specialised type <code>G (G A -> A)</code> is concerned, it is conceivable that the involved <code>G A -> A</code> functions might not be natural in <code>A</code>.</p></li>
<li><p>Accordingly, a rank-2 function that takes a <code>Pos G</code>, such as the argument to <code>reveal</code>, can be mapped over <code>chart</code>, but not <code>chartDist</code>.</p></li>
<li><p>There is no way to obtain the impredicative type of <code>chart</code>, or the rank-3 type of <code>reveal</code>, through <code>distribute</code>.</p></li>
</ul>
<p>To put it in another way, <code>chartDist</code> doesn’t have a type strong enough to, on its own, ensure that it provides natural, polymorphic extractors, and <code>Distributive</code> is not enough to implement a <code>chart</code> which provides such guarantees.</p>
<p>Still, not all is lost. If there is a way to use the laws of <code>Distributive</code> to show that the extractors of <code>chartDist</code> are natural, we should be able to claim <code>chart</code> and <code>chartDist</code> are morally the same, providing the same extractors with subtly different types.</p>
<p>(Meta note: while I believe the following argument suffices for the task at hand, it is not as crystalline as the derivations elsewhere in this post. Upgrading it to a proper proof will probably require some tricky parametricity maneuver which I haven’t managed to fully figure out yet.)</p>
<p>Let’s turn to the composition law, the one we haven’t touched so far:</p>
<div class="sourceCode" id="cb50"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb50-1"><a href="#cb50-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> getCompose <span class="op">.</span> distribute <span class="ot">=</span> distribute <span class="op">.</span> <span class="fu">fmap</span> distribute <span class="op">.</span> getCompose</span></code></pre></div>
<p>That is, given some <code>m :: Compose fo fi (g a)</code> (“o” is for outer, and “i” for inner):</p>
<div class="sourceCode" id="cb51"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb51-1"><a href="#cb51-1" aria-hidden="true" tabindex="-1"></a>getCompose <span class="op"><$></span> distribute m <span class="ot">=</span> distribute (distribute <span class="op"><$></span> getCompose m)</span></code></pre></div>
<p>Let’s use <code>distribute m = (\p -> p <$> m) <$> chartDist</code> on the left-hand side, and on the outer <code>distribute</code> on the right-hand side:</p>
<div class="sourceCode" id="cb52"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb52-1"><a href="#cb52-1" aria-hidden="true" tabindex="-1"></a>getCompose <span class="op"><$></span> ((\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> chartDist)</span>
<span id="cb52-2"><a href="#cb52-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\q <span class="ot">-></span> q <span class="op"><$></span> (distribute <span class="op"><$></span> getCompose m)) <span class="op"><$></span> chartDist</span></code></pre></div>
<p>Note that the left-hand side <code>chartDist</code> has type <code>g (g a -> a)</code>, while the right-hand side one has type <code>g (g (fi a) -> fi a)</code>. Since we can’t take for granted that the extractors provided by them (which are bound to <code>p</code> and <code>q</code>, respectively) are natural, it is important to keep track of this difference.</p>
<p>Tidying the equation a little further, we get:</p>
<div class="sourceCode" id="cb53"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb53-1"><a href="#cb53-1" aria-hidden="true" tabindex="-1"></a>getCompose <span class="op"><$></span> ((\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> chartDist)</span>
<span id="cb53-2"><a href="#cb53-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\q <span class="ot">-></span> q <span class="op"><$></span> (distribute <span class="op"><$></span> getCompose m)) <span class="op"><$></span> chartDist</span>
<span id="cb53-3"><a href="#cb53-3" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> getCompose (p <span class="op"><$></span> m)) <span class="op"><$></span> chartDist</span>
<span id="cb53-4"><a href="#cb53-4" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\q <span class="ot">-></span> q <span class="op">.</span> distribute <span class="op"><$></span> getCompose m) <span class="op"><$></span> chartDist</span>
<span id="cb53-5"><a href="#cb53-5" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> <span class="fu">fmap</span> p <span class="op"><$></span> getCompose m) <span class="op"><$></span> chartDist</span>
<span id="cb53-6"><a href="#cb53-6" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\q <span class="ot">-></span> q <span class="op">.</span> distribute <span class="op"><$></span> getCompose m) <span class="op"><$></span> chartDist</span></code></pre></div>
<p>On either side of the equation, we have <code>fmap</code> being used to obtain a <code>g (fo (fi a))</code> result. That being so, any <code>fo (fi a)</code> value that, thanks to <code>fmap</code>, shows up in the left-hand side must also show up in the right-hand side. More precisely, given any <code>p :: g a -> a</code> drawn from <code>chartDist</code> on the left-hand side, there must be some <code>q :: g (fi a) -> fi a</code> drawn from the <code>chartDist</code> on the right hand side such that…</p>
<div class="sourceCode" id="cb54"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb54-1"><a href="#cb54-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> p <span class="op"><$></span> getCompose m <span class="ot">=</span> q <span class="op">.</span> distribute <span class="op"><$></span> getCompose m</span></code></pre></div>
<p>… and vice versa. That allows us to reason about <code>p</code> and <code>q</code>, which amount to the extractors drawn from <code>chartDist</code> we are interested in.</p>
<p>As neither <code>p</code> nor <code>q</code> involve <code>fo</code>, and the equation must hold for all choices of <code>fo</code>, we can freely consider the case in which it is <code>Identity</code>, or anything else that has an injective <code>fmap</code>. If <code>fmap</code> is injective, the equation further simplifies to:</p>
<div class="sourceCode" id="cb55"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb55-1"><a href="#cb55-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> p <span class="ot">=</span> q <span class="op">.</span> distribute</span></code></pre></div>
<p>Now, <code>fmap p :: fi (g a) -> fi a</code> cannot affect the <code>fi</code> shape; therefore, the same holds for <code>q . distribute :: fi (g a) -> fi a</code>. <code>distribute :: fi (g a) -> g (fi a)</code> is natural in <code>fi</code>, and so it, too, can’t affect the <code>fi</code> shape. It follows that <code>q :: g (fi a) -> fi a</code> is also unable to affect the <code>fi</code> shape.</p>
<p>Zooming back out, we have just established that, if the composition law holds, <code>chartDist :: g (g (fi a) -> fi a)</code> only provides extractors that preserve the <code>fi</code> shape. <code>chartDist</code>, however, is defined as <code>distribute id :: forall b. g (g b -> b)</code>, which is fully polymorphic on the element type <code>b</code>. That being so, if there is a way for <code>distribute id</code> to somehow produce non-natural extractors, it cannot possibly rely in any way about the specifics of <code>b</code>. That, in particular, rules out any means of, given <code>b ~ fi a</code> for some functor <code>fi</code>, producing just non-natural extractors that preserve the <code>fi</code> shape: such a distinction cannot be expressed. We must conclude, therefore, that if the composition law holds <code>chartDist</code> can only provide natural extractors, as we hoped to show.</p>
<p>The converse of this conclusion, by the way, also holds: assuming the identity law holds, if all <code>q</code> drawn from <code>chartDist</code> are natural, the composition law must hold. To show that, we can use the fact that, for a natural <code>q :: forall x. g x -> x</code>, <code>q chartDist = q</code> holds, just like it does for <code>chart</code>:</p>
<div class="sourceCode" id="cb56"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb56-1"><a href="#cb56-1" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist <span class="ot">=</span> u</span>
<span id="cb56-2"><a href="#cb56-2" aria-hidden="true" tabindex="-1"></a>q ((\p <span class="ot">-></span> p u) <span class="op"><$></span> chartDist)) <span class="ot">=</span> q u</span>
<span id="cb56-3"><a href="#cb56-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- Since q is natural, q . fmap f = f . q</span></span>
<span id="cb56-4"><a href="#cb56-4" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) (q chartDist) <span class="ot">=</span> q u</span>
<span id="cb56-5"><a href="#cb56-5" aria-hidden="true" tabindex="-1"></a>(q chartDist) u <span class="ot">=</span> q u</span>
<span id="cb56-6"><a href="#cb56-6" aria-hidden="true" tabindex="-1"></a>q chartDist <span class="ot">=</span> q</span></code></pre></div>
<p>As a consequence, <code>q . distribute = fmap q</code>:</p>
<div class="sourceCode" id="cb57"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb57-1"><a href="#cb57-1" aria-hidden="true" tabindex="-1"></a>q (distribute m)</span>
<span id="cb57-2"><a href="#cb57-2" aria-hidden="true" tabindex="-1"></a>q ((\p <span class="ot">-></span> p <span class="op"><$></span> m) <span class="op"><$></span> chartDist)</span>
<span id="cb57-3"><a href="#cb57-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- q is natural</span></span>
<span id="cb57-4"><a href="#cb57-4" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p <span class="op"><$></span> m) (q chartDist)</span>
<span id="cb57-5"><a href="#cb57-5" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p <span class="op"><$></span> m) q</span>
<span id="cb57-6"><a href="#cb57-6" aria-hidden="true" tabindex="-1"></a>q <span class="op"><$></span> m</span></code></pre></div>
<p>We can now return to the rearranged version of the composition law we were dealing with in the preceding argument, this time without taking it for granted:</p>
<div class="sourceCode" id="cb58"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb58-1"><a href="#cb58-1" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> <span class="fu">fmap</span> p <span class="op"><$></span> getCompose m) <span class="op"><$></span> chartDist</span>
<span id="cb58-2"><a href="#cb58-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (\q <span class="ot">-></span> q <span class="op">.</span> distribute <span class="op"><$></span> getCompose m) <span class="op"><$></span> chartDist</span></code></pre></div>
<p>By the above, however, if <code>q</code> is natural the right-hand side amounts to…</p>
<div class="sourceCode" id="cb59"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb59-1"><a href="#cb59-1" aria-hidden="true" tabindex="-1"></a>(\q <span class="ot">-></span> <span class="fu">fmap</span> q <span class="op"><$></span> getCompose m) <span class="op"><$></span> chartDist</span></code></pre></div>
<p>… which is the same as the left-hand side.</p>
<h3 id="in-summary">In summary</h3>
<p>After quite a long ride, we have managed to shed some light on the connection between <code>Distributive</code> and <code>Representable</code>:</p>
<ul>
<li><p>Every <code>Distributive</code> is indeed <code>Representable</code>, even though, as expected, <code>Representable</code> cannot be implemented in terms of <code>distribute</code>.</p></li>
<li><p>The connection is mediated by choosing <code>forall x. g x -> x</code>, the type of polymorphic extractors, as a default representation, encoded here as the <code>Revealable</code> class. It can then be shown that this representation is mirrored in <code>Distributive</code> by <code>chartDist = distribute id :: Distributive g => g (g a -> a)</code>, which gives a corresponding characterisation of <code>Distributive</code> in terms of extractors.</p></li>
<li><p>The single-shapedness characteristic of both distributive and representable functors follows from the identity law of <code>Distributive</code>.</p></li>
<li><p>The composition law plays an important, if unobvious, role in the connection, as it ensures the naturality of the extractors provided by <code>chartDist</code>, a property that can’t be established on the basis of the involved types.</p></li>
</ul>
<h2 id="the-select-loophole">The Select loophole</h2>
<p>There is one aspect of our investigation that is worth a closer look. All the concern with establishing that <code>chartDist</code> can only provide natural extractors, which kept us busy for a good chunk of the previous section, might have felt surprising. <code>chartDist</code>, after all…</p>
<div class="sourceCode" id="cb60"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb60-1"><a href="#cb60-1" aria-hidden="true" tabindex="-1"></a><span class="ot">chartDist ::</span> <span class="kw">forall</span> g a<span class="op">.</span> <span class="dt">Distributive</span> g <span class="ot">=></span> g (g a <span class="ot">-></span> a)</span></code></pre></div>
<p>… is fully polymorphic in <code>a</code>, and therefore its definition cannot rely on anything specific about <code>a</code>. That being so, it may seem outlandish to suppose that specialising <code>chartDist</code> to, say, <code>g (g Integer -> Integer)</code> might somehow bring forth non-natural <code>g Integer -> Integer</code> extractors that perform <code>Integer</code>-specific operations.</p>
<p>To illustrate why the naturality of extractors is, in fact, a relevant issue, let’s consider the curious case of <a href="https://hackage.haskell.org/package/transformers-0.6.0.2/docs/Control-Monad-Trans-Select.html"><code>Select</code></a>:</p>
<div class="sourceCode" id="cb61"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb61-1"><a href="#cb61-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- A paraphrased, non-transformer version of Select.</span></span>
<span id="cb61-2"><a href="#cb61-2" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Select</span> r a <span class="ot">=</span> <span class="dt">Select</span> {<span class="ot"> runSelect ::</span> (a <span class="ot">-></span> r) <span class="ot">-></span> a }</span>
<span id="cb61-3"><a href="#cb61-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb61-4"><a href="#cb61-4" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Functor</span> (<span class="dt">Select</span> r) <span class="kw">where</span></span>
<span id="cb61-5"><a href="#cb61-5" aria-hidden="true" tabindex="-1"></a> <span class="fu">fmap</span> f u <span class="ot">=</span> <span class="dt">Select</span> <span class="op">$</span> \k <span class="ot">-></span> f (u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k (f a))</span></code></pre></div>
<p>(A <code>Select r a</code> value can be thought of as a way to choose an <code>a</code> value based on some user-specified criterion, expressed as an <code>a -> r</code> function.)</p>
<p>Corner cases such as <code>r ~ ()</code> aside, <code>Select r</code> cannot be <code>Representable</code>, as that would require it to be isomorphic to a function functor; that being so, it should be similarly ill-suited for <code>Distributive</code>. In spite of that, there is a nontrivial implementation of a <code>Select r</code> combinator with the type <code>chartDist</code> would have: <a href="#fn8" class="footnote-ref" id="fnref8" role="doc-noteref"><sup>8</sup></a></p>
<div class="sourceCode" id="cb62"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb62-1"><a href="#cb62-1" aria-hidden="true" tabindex="-1"></a><span class="ot">chartSelect ::</span> <span class="dt">Select</span> r (<span class="dt">Select</span> r a <span class="ot">-></span> a)</span>
<span id="cb62-2"><a href="#cb62-2" aria-hidden="true" tabindex="-1"></a>chartSelect <span class="ot">=</span> <span class="dt">Select</span> <span class="op">$</span> \k <span class="ot">-></span> \u <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k (<span class="fu">const</span> a)</span></code></pre></div>
<p>What’s more, <code>chartSelect</code> follows the law of extractors:</p>
<div class="sourceCode" id="cb63"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb63-1"><a href="#cb63-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Goal:</span></span>
<span id="cb63-2"><a href="#cb63-2" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) <span class="op"><$></span> chartSelect <span class="ot">=</span> u</span>
<span id="cb63-3"><a href="#cb63-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- LHS</span></span>
<span id="cb63-4"><a href="#cb63-4" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) <span class="op"><$></span> chartSelect</span>
<span id="cb63-5"><a href="#cb63-5" aria-hidden="true" tabindex="-1"></a>(\p <span class="ot">-></span> p u) <span class="op"><$></span> <span class="dt">Select</span> <span class="op">$</span> \k <span class="ot">-></span> \u <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k (<span class="fu">const</span> a)</span>
<span id="cb63-6"><a href="#cb63-6" aria-hidden="true" tabindex="-1"></a><span class="dt">Select</span> <span class="op">$</span> \k' <span class="ot">-></span></span>
<span id="cb63-7"><a href="#cb63-7" aria-hidden="true" tabindex="-1"></a> (\p <span class="ot">-></span> p u) (\u <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k' ((\p <span class="ot">-></span> p u) (<span class="fu">const</span> a)))</span>
<span id="cb63-8"><a href="#cb63-8" aria-hidden="true" tabindex="-1"></a><span class="dt">Select</span> <span class="op">$</span> \k' <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k' ((\p <span class="ot">-></span> p u) (<span class="fu">const</span> a))</span>
<span id="cb63-9"><a href="#cb63-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Select</span> <span class="op">$</span> \k' <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k' (<span class="fu">const</span> a u)</span>
<span id="cb63-10"><a href="#cb63-10" aria-hidden="true" tabindex="-1"></a><span class="dt">Select</span> <span class="op">$</span> \k' <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k' a</span>
<span id="cb63-11"><a href="#cb63-11" aria-hidden="true" tabindex="-1"></a>u <span class="co">-- LHS = RHS</span></span></code></pre></div>
<p>That means the <code>distribute</code> candidate we get out of <code>chartSelect</code>…</p>
<div class="sourceCode" id="cb64"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb64-1"><a href="#cb64-1" aria-hidden="true" tabindex="-1"></a><span class="ot">nonDistribute ::</span> <span class="dt">Functor</span> f <span class="ot">=></span> f (<span class="dt">Select</span> r a) <span class="ot">-></span> <span class="dt">Select</span> r (f a)</span>
<span id="cb64-2"><a href="#cb64-2" aria-hidden="true" tabindex="-1"></a>nonDistribute m <span class="ot">=</span> <span class="dt">Select</span> <span class="op">$</span></span>
<span id="cb64-3"><a href="#cb64-3" aria-hidden="true" tabindex="-1"></a> \k <span class="ot">-></span> (\u <span class="ot">-></span> u <span class="ot">`runSelect`</span> \a <span class="ot">-></span> k (a <span class="op"><$</span> m)) <span class="op"><$></span> m</span></code></pre></div>
<p>… follows the identity law. As <code>Select r</code> is not supposed to be <code>Distributive</code>, we expect <code>nonDistribute</code> to break the composition law, and that is indeed what happens. <a href="#fn9" class="footnote-ref" id="fnref9" role="doc-noteref"><sup>9</sup></a></p>
<p>Now, by the earlier arguments about the naturality of extractors, if a candidate implementation of <code>chartDist</code> follows the extractors law and only provides natural extractors, the corresponding <code>distribute</code> must follow the composition law. Since <code>chartSelect</code> follows the extractors law but doesn’t give rise to a lawful <code>distribute</code>, we must conclude that it provides non-natural extractors. How does that come to pass?</p>
<p>Every criterion function <code>k :: a -> r</code> gives rise to a non-natural extractor for <code>Select r a</code>, namely <code>\u -> u `runSelect` k :: Select a r -> a</code>. <code>chartSelect</code> indirectly makes all these non-natural extractors available through its own criterion argument, the <code>k</code> that shows up in its definition. (How the encoding works can be seen in the verification above of the law of extractors: note how performing the <code>fmap</code> between the third and fourth lines of the proof requires replacing <code>k :: (Select r a -> a) -> r</code> with <code>k' :: a -> r</code>.)</p>
<p>Non-naturality sneaking into <code>chartSelect</code> has to do with <code>Select r</code> not being a strictly positive functor; that is, it has an occurrence of the element type variable, <code>a</code>, to the left of a function arrow. <a href="#fn10" class="footnote-ref" id="fnref10" role="doc-noteref"><sup>10</sup></a> The lack of strict positivity creates a loophole, through which things can be incorporated to a <code>Select r a</code> value without being specified. It is a plausible conjecture that the composition law of <code>Distributive</code> is a way of ruling out functors that aren’t strictly positive, with lack of strict positivity being the only possible source of non-naturality in <code>chartDist</code>, and any non-trivial lack of strict positivity leading to non-naturality and the composition law being broken. <a href="#fn11" class="footnote-ref" id="fnref11" role="doc-noteref"><sup>11</sup></a></p>
<h2 id="further-reading">Further reading</h2>
<p>There are other interesting ways of approaching <code>Distributive</code> and <code>Representable</code> that I haven’t covered here to avoid making this post longer than it already is. Here are a few suggestions for further reading:</p>
<ul>
<li><p>Chris Penner’s <a href="https://chrispenner.ca/posts/adjunction-battleship"><em>Adjunctions and Battleship</em></a> post is a fine introduction to <a href="https://hackage.haskell.org/package/adjunctions-4.4/docs/Data-Functor-Adjunction.html"><code>Adjunction</code></a>, the class for <strong>Hask</strong>-<strong>Hask</strong> adjunctions, which provides an alternative encoding of <code>Representable</code>.</p></li>
<li><p>The following Stack Overflow answers by Conor McBride on <em>Naperian functors</em>, “Naperian” here being an alternative name for <code>Representable</code>:</p>
<ul>
<li><p><a href="https://stackoverflow.com/a/46502280/2751851"><em>Which Haskell Functors are equivalent to the Reader functor</em></a>, which introduces Naperian functors in a style reminiscent of the <code>askRep</code>-centric formuation of <code>Representable</code> discussed here.</p></li>
<li><p><a href="https://stackoverflow.com/a/13100857/2751851"><em>Writing cojoin or cobind for n-dimensional grid type</em></a>, which includes an outline of how Naperian functors are handled by container theory.</p></li>
</ul></li>
</ul>
<p>On a final note, there is a <a href="https://github.com/ekmett/distributive/blob/117377d7ba38efc5b115169b565dfb80de8ad407/src/Data/Rep/Internal.hs">reworking of <code>Representable</code></a> being developed as part of a potential future release of the <em>distributive</em> package. It aims at unifying the presentations of distributive into a single class that fits equally well the various use cases. An overview of how this new formulation could be a nice topic for a future, follow-up post.</p>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>The <code>Data.Distributive</code> documentation, as of the version 0.6.2.1 of the <em>distributive</em> package, mentions a different set of properties in lieu of these laws, the crucial one being <code>distribute . distribute = id</code>. Though that is a viable approach, I feel that in the context of what this post aims at such a formulation raises more questions than they answer. (For instance, regarding <code>distribute . distribute = id</code>: Are there two <code>Distributive</code> instances involved? If so, how are we supposed to check that an individual instance is lawful? Does that law correspond to anything from <code>Traversable</code>?) That being so, I have chosen to take a step back and regard the “dual to <code>Traversable</code>” formulation as the starting point.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>The name <code>flap</code>, which I have borrowed from <a href="https://hackage.haskell.org/package/relude-1.0.0.1/docs/Relude-Functor-Fmap.html#v:flap"><em>relude</em></a>, is a play on how <code>distribute @((->) _) @((->) _)</code> turns out to be <code>flip</code>.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>Here is a proof of its lawfulness:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Goal (identity law):</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> runIdentity <span class="op">.</span> distributeRep <span class="ot">=</span> runIdentity</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> runIdentity <span class="op">.</span> distributeRep <span class="co">-- LHS</span></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> runIdentity <span class="op">.</span> tabulate <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- tabulate is natural</span></span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> <span class="fu">fmap</span> runIdentity <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- flap follows the identity law</span></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> runIdentity <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> <span class="fu">index</span> <span class="op">.</span> runIdentity</span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- tabulate . index = id</span></span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a>runIdentity <span class="co">-- LHS = RHS</span></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="co">-- Goal (composition law):</span></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> getCompose <span class="op">.</span> distributeRep</span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> distributeRep <span class="op">.</span> <span class="fu">fmap</span> distributeRep <span class="op">.</span> getCompose</span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a>distributeRep <span class="op">.</span> <span class="fu">fmap</span> distributeRep <span class="op">.</span> getCompose <span class="co">-- RHS</span></span>
<span id="cb16-17"><a href="#cb16-17" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span> <span class="op">.</span> <span class="fu">fmap</span> tabulate</span>
<span id="cb16-18"><a href="#cb16-18" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span> <span class="fu">fmap</span> flap <span class="op">.</span> <span class="fu">fmap</span> (<span class="fu">fmap</span> <span class="fu">index</span>) <span class="op">.</span> getCompose</span>
<span id="cb16-19"><a href="#cb16-19" aria-hidden="true" tabindex="-1"></a><span class="co">-- index . tabulate = id</span></span>
<span id="cb16-20"><a href="#cb16-20" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> flap <span class="op">.</span> <span class="fu">fmap</span> (<span class="fu">fmap</span> <span class="fu">index</span>) <span class="op">.</span> getCompose</span>
<span id="cb16-21"><a href="#cb16-21" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> flap <span class="op">.</span> getCompose <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span>
<span id="cb16-22"><a href="#cb16-22" aria-hidden="true" tabindex="-1"></a><span class="co">-- flap follows the composition law</span></span>
<span id="cb16-23"><a href="#cb16-23" aria-hidden="true" tabindex="-1"></a>tabulate <span class="op">.</span> <span class="fu">fmap</span> getCompose <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span>
<span id="cb16-24"><a href="#cb16-24" aria-hidden="true" tabindex="-1"></a><span class="co">-- tabulate is natural</span></span>
<span id="cb16-25"><a href="#cb16-25" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> getCompose <span class="op">.</span> tabulate <span class="op">.</span> flap <span class="op">.</span> <span class="fu">fmap</span> <span class="fu">index</span></span>
<span id="cb16-26"><a href="#cb16-26" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> getCompose <span class="op">.</span> distributeRep <span class="co">-- RHS = LHS</span></span></code></pre></div>
<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn4" role="doc-endnote"><p>That is a manifestation of the Yoneda lemma. For a Haskell-oriented introduction to it, see Dan Piponi’s <a href="http://blog.sigfpe.com/2006/11/yoneda-lemma.html"><em>Reverse Engineering Machines with the Yoneda Lemma</em></a>.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p><code>askRep</code> is indeed <code>ask</code> for <code>MonadReader (Rep g) g</code>; accordingly, <code>tabulate</code> is <code>asks</code>/<code>reader</code>.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>On a technical note, given that the type of <code>chart</code> amounts to <code>g (forall x. g x -> x)</code> using these definitions as written requires the <code>ImpredicativeTypes</code> extension and, ideally, GHC 9.2 or above. Doing it without <code>ImpredicativeTypes</code> would require making <code>Pos g</code> a <code>newtype</code> instead of a mere synonym.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn7" role="doc-endnote"><p>In brief: two implementations of <code>distribute :: f (g a) -> g (f a)</code> might differ by what they do to the <code>a</code> values, <code>f</code> shapes, or <code>g</code> shapes. Naturality means <code>a</code> and <code>f</code> can’t be affected by <code>distribute</code>, and so any difference would have to arise from what is done to <code>g</code>. However, the identity law means the <code>g</code> shape can’t be affected either. Therefore, implementations which follow the identity law can’t differ.<a href="#fnref7" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn8" role="doc-endnote"><p>I originally realised it is possible through <a href="https://stackoverflow.com/a/39736535/2751851">a Stack Overflow answer by Sergei Winitzki</a>. I thank him for helping to drive this post to completion, as thinking about <code>Select</code> was instrumental in putting the pieces together.<a href="#fnref8" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn9" role="doc-endnote"><p>Sparing the very messy full proof, the gist of it has to do with the <code>(<$)</code> trick <code>nonDistribute</code> uses to borrow the shape of <code>m</code> in order to have something to feed the <code>k :: f a -> r</code> criterion. In the left-hand side of the composition law, <code>fmap getCompose . distribute</code>, the trick is applied once, at the outermost level, while in the right-hand side, <code>distribute . fmap distribute. getCompose</code>, thanks to the <code>fmap distribute</code> it is also done inside of the outer layer. That being so, there is no way the two sides might be equal.<a href="#fnref9" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn10" role="doc-endnote"><p>Though it doesn’t explicitly mention strict positivity, Michael Snoyman’s <a href="https://www.fpcomplete.com/blog/2016/11/covariance-contravariance/"><em>Covariance and Contravariance</em></a> is an useful primer on polarity, production and consumption in functors. In particular, the <code>CallbackRunner</code> example in the “Positive and negative position” section towards the end is a <code>Functor</code> that isn’t strictly positive.<a href="#fnref10" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn11" role="doc-endnote"><p>On a tangential note, the lack of strict positivity also breaks down the intuitive notion of the shape, as something that can be distinguished from the <code>a</code> values contained or produced by some functorial value <code>f a</code>. While <code>chartSelect</code> abiding by the law of extractors suggests that we should think of <code>Select r</code> as single-shaped, it is hard to even tell what a shape is supposed to be in this case. If <code>Select r a</code> were a garden-variety function type, we might say that there is one <code>a</code> result for every possible <code>a -> r</code> criterion. However, the number of possible <code>a -> r</code> functions also depends on the choice of <code>a</code>. As a result, the number of inhabitants (that is, distinct possible values) of <code>Select r a</code> grows much faster than linearly with the number of inhabitants of <code>a</code>. Were we to say <code>Select r</code> is a single-shaped functor, we would have to concede the shape is <a href="https://tvtropes.org/pmwiki/pmwiki.php/Main/BiggerOnTheInside">is bigger on the inside</a>.<a href="#fnref11" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
<div id="comment-nav" class="pure-g-r no-print">
<div class="pure-u-1-4">
<a id="gh-comments-button" class="pure-button" href="https://github.com/duplode/duplode.github.io/issues/17">Comment on GitHub</a>
</div>
<div class="pure-u-1-4">
</div>
<div class="pure-u-1-4">
<a id="discourse-button" class="pure-button" href="https://discourse.haskell.org/t/4043">Discourse topic</a>
</div>
<div class="pure-u-1-4">
</div>
</div>
<div><div class="license">
<p>
<span class="inline-centered">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="//i.creativecommons.org/l/by-sa/4.0/80x15.png" /></a>
</span>
<span class="inline-centered">
Post licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
</span>
</p>
</div>
</div>
]]></description>
<pubDate>2022-02-07T16:55:00-03:00</pubDate>
<guid>https://duplode.github.io/posts/every-distributive-is-representable.html</guid>
<dc:creator>Daniel Mlot</dc:creator>
</item>
<item>
<title>Divisible and the Monoidal Quartet</title>
<link>https://duplode.github.io/posts/divisible-and-the-monoidal-quartet.html</link>
<description><![CDATA[
<p>A recent blog post by Gabriella Gonzalez, <a href="https://www.haskellforall.com/2021/10/co-applicative-programming-style.html"><em>Co-Applicative programming style</em></a>, has sparked discussion on ergonomic ways to make use of <a href="https://hackage.haskell.org/package/contravariant-1.5.5">the <code>Divisible</code> type class</a>. The conversation pointed to an interesting rabbit hole, and jumping into it resulted in these notes, in which I attempt to get a clearer view of picture of the constellation of monoidal functor classes that <code>Divisible</code> belongs to. The gist of it is that “<code>Divisible</code> is a contravariant <code>Applicative</code>, and <code>Decidable</code> is a contravariant <code>Alternative</code>” is not a full picture of the relationships between the classes, as there are a few extra connections that aren’t obvious to the naked eye.</p>
<div>
</div>
<!--more-->
<p>Besides Gabriella’s post, which is an excellent introduction to <code>Divisible</code>, I recommend as background reading Tom Ellis’ <a href="http://h2.jaguarpaw.co.uk/posts/alternatives-convert-products-to-sums/"><em><code>Alternatives</code> convert products to sums</em></a>, which conveys the core intuition about monoidal functor classes in an accessible manner. There is a second post by Tom, <a href="http://h2.jaguarpaw.co.uk/posts/mysterious-incomposability-of-decidable/"><em>The Mysterious Incomposability of <code>Decidable</code></em></a>, that this article will be in constant dialogue with, in particular as a source of examples. From now on I will refer to it as “the <em>Decidable</em> post”. Thanks to Gabriella and Tom for inspiring the writing of this article.</p>
<p>For those of you reading with GHCi on the side, the key general definitions in this post are available from <a href="../demos/Quartet/Combinators.hs">this <code>.hs</code> file</a>.</p>
<h2 id="applicative">Applicative</h2>
<p>As I hinted at the introduction, this post is not solely about <code>Divisible</code>, but more broadly about monoidal functor classes. To start from familiar ground and set up a reference point, I will first look at the best known of those classes, <code>Applicative</code>. We won’t, however, stick with the usual presentation of <code>Applicative</code> in terms of <code>(<*>)</code>, as it doesn’t generalise to the other classes we’re interested in. Instead, we will switch to the monoidal presentation: <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a></p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="ot">zipped ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f (a, b)</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>zipped <span class="ot">=</span> liftA2 (,)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a><span class="co">-- An operator spelling, for convenience.</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ot">(&*&) ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f (a, b)</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>(<span class="op">&*&</span>) <span class="ot">=</span> zipped</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="op">&*&</span></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true" tabindex="-1"></a><span class="ot">unit ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f ()</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true" tabindex="-1"></a>unit <span class="ot">=</span> <span class="fu">pure</span> ()</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- Laws:</span></span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- unit &*& v ~ v</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a><span class="co">-- u &*& unit ~ u</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- (u &*& v) &*& w ~ u &*& (v &*& w)</span></span></code></pre></div>
<p>(Purely for the sake of consistency, I will try to stick to the <code>Data.Functor.Contravariant.Divisible</code> naming conventions for functions like <code>zipped</code>.)</p>
<p>The matter with <code>(<*>)</code> (and also <code>liftA2</code>) that stops it from being generalised for our purposes is that it leans heavily on the fact that <strong>Hask</strong> is a <em>Cartesian closed category</em>, with pairs as the relevant product. Without that, the currying and the partial application we rely on when writing in applicative style become unfeasible.</p>
<p>While keeping ourselves away from <code>(<*>)</code> and <code>liftA2</code>, we can recover, if not the full flexibility, the power of applicative style with a variant of <code>liftA2</code> that takes an uncurried function:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">lizip ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> ((a, b) <span class="ot">-></span> c) <span class="ot">-></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f c</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>lizip f u v <span class="ot">=</span> <span class="fu">fmap</span> f (zipped u v)</span></code></pre></div>
<p>(That is admittedly a weird name; all the clashing naming conventions around this topic has left me with few good options.)</p>
<p>On a closing note for this section, my choice of operator for <code>zipped</code> is motivated by the similarity with <code>(&&&)</code> from <code>Control.Arrow</code>:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(&&&) ::</span> <span class="dt">Arrow</span> p <span class="ot">=></span> p a b <span class="ot">-></span> p a c <span class="ot">-></span> p a (b, c)</span></code></pre></div>
<p>In particular, <code>(&*&)</code> for the function <code>Applicative</code> coincides with <code>(&&&)</code> for the function <code>Arrow</code>.</p>
<p>Leaning on connections like this one, I will use <code>Control.Arrow</code> combinators liberally, beginning with the definition of the following two convenience functions that will show up shortly:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ot">dup ::</span> a <span class="ot">-></span> (a, a)</span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>dup <span class="ot">=</span> <span class="fu">id</span> <span class="op">&&&</span> <span class="fu">id</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ot">forget ::</span> <span class="dt">Either</span> a a <span class="ot">-></span> a</span>
<span id="cb4-5"><a href="#cb4-5" aria-hidden="true" tabindex="-1"></a>forget <span class="ot">=</span> <span class="fu">id</span> <span class="op">|||</span> <span class="fu">id</span></span></code></pre></div>
<h2 id="divisible">Divisible</h2>
<p>As summarised at the beginning of the <em>Decidable</em> post, while <code>Applicative</code> converts products to products covariantly, <code>Divisible</code> converts products to products contravariantly. From that point of view, I will take <code>divided</code>, the counterpart to <code>zipped</code>, as the fundamental combinator of the class:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- This is the divided operator featured on Gabriella's post, soon to</span></span>
<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- become available from Data.Functor.Contravariant.Divisible</span></span>
<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="ot">(>*<) ::</span> <span class="dt">Divisible</span> k <span class="ot">=></span> k a <span class="ot">-></span> k b <span class="ot">-></span> k (a, b)</span>
<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a>(<span class="op">>*<</span>) <span class="ot">=</span> divided</span>
<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="op">>*<</span></span>
<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- Laws:</span></span>
<span id="cb5-8"><a href="#cb5-8" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb5-9"><a href="#cb5-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- conquered >*< v ~ v</span></span>
<span id="cb5-10"><a href="#cb5-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- u >*< conquered ~ u</span></span>
<span id="cb5-11"><a href="#cb5-11" aria-hidden="true" tabindex="-1"></a><span class="co">-- (u >*< v) >*< w ~ u >*< (v >*< w)</span></span></code></pre></div>
<p>Recovering <code>divide</code> from <code>divided</code> is straightforward, and entirely analogous to how <code>lizip</code> can be obtained from <code>zipped</code>:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="ot">divide ::</span> <span class="dt">Divisible</span> k <span class="ot">=></span> (a <span class="ot">-></span> (b, c)) <span class="ot">-></span> k b <span class="ot">-></span> k c <span class="ot">-></span> k a</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>divide f <span class="ot">=</span> contramap f (divided u v)</span></code></pre></div>
<p>Lessened currying aside, we might say that <code>divide</code> plays the role of <code>liftA2</code> in <code>Divisible</code>.</p>
<p>It’s about time for an example. For that, I will borrow the one from Gabriella’s post:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Point</span> <span class="ot">=</span> <span class="dt">Point</span> {<span class="ot"> x ::</span> <span class="dt">Double</span>,<span class="ot"> y ::</span> <span class="dt">Double</span>,<span class="ot"> z ::</span> <span class="dt">Double</span> }</span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> <span class="dt">Show</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ot">nonNegative ::</span> <span class="dt">Predicate</span> <span class="dt">Double</span></span>
<span id="cb7-5"><a href="#cb7-5" aria-hidden="true" tabindex="-1"></a>nonNegative <span class="ot">=</span> <span class="dt">Predicate</span> (<span class="dv">0</span> <span class="op"><=</span>)</span>
<span id="cb7-6"><a href="#cb7-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb7-7"><a href="#cb7-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- (>$<) = contramap</span></span>
<span id="cb7-8"><a href="#cb7-8" aria-hidden="true" tabindex="-1"></a><span class="ot">nonNegativeOctant ::</span> <span class="dt">Predicate</span> <span class="dt">Point</span></span>
<span id="cb7-9"><a href="#cb7-9" aria-hidden="true" tabindex="-1"></a>nonNegativeOctant <span class="ot">=</span></span>
<span id="cb7-10"><a href="#cb7-10" aria-hidden="true" tabindex="-1"></a> adapt <span class="op">>$<</span> nonNegative <span class="op">>*<</span> nonNegative <span class="op">>*<</span> nonNegative</span>
<span id="cb7-11"><a href="#cb7-11" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb7-12"><a href="#cb7-12" aria-hidden="true" tabindex="-1"></a> adapt <span class="ot">=</span> x <span class="op">&&&</span> y <span class="op">&&&</span> z</span></code></pre></div>
<p>The slight distortion to Gabriella’s style in using <code>(&&&)</code> to write <code>adapt</code> pointfree is meant to emphasise how that deconstructor can be cleanly assembled out of the component projection functions <code>x</code>, <code>y</code> and <code>z</code>. Importantly, that holds in general: pair-producing functions <code>a -> (b, c)</code> are isomorphic <code>(a -> b, a -> c)</code> pairs of projections. That gives us a variant of <code>divide</code> that takes the projections separately:</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ot">tdivide ::</span> <span class="dt">Divisible</span> k <span class="ot">=></span> (a <span class="ot">-></span> b) <span class="ot">-></span> (a <span class="ot">-></span> c) <span class="ot">-></span> k b <span class="ot">-></span> k c <span class="ot">-></span> k a</span>
<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a>tdivide f g u v <span class="ot">=</span> divide (f <span class="op">&&&</span> g) u v</span></code></pre></div>
<p>Besides offering an extra option with respect to ergonomics, <code>tdivide</code> hints at extra structure available from the <code>Divisible</code> class. Let’s play with the definitions a little:</p>
<div class="sourceCode" id="cb9"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a>tdivide f g u v</span>
<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a>divide (f <span class="op">&&&</span> g) u v</span>
<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a>contramap (f <span class="op">&&&</span> g) (divided u v)</span>
<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a>contramap ((f <span class="op">***</span> g) <span class="op">.</span> dup) (divided u v)</span>
<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>(contramap dup <span class="op">.</span> contramap (f <span class="op">***</span> g)) (divided u v)</span>
<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a>contramap dup (divided (contramap f u) (contramap g v))</span>
<span id="cb9-7"><a href="#cb9-7" aria-hidden="true" tabindex="-1"></a>divide dup (contramap f u) (contramap g v)</span></code></pre></div>
<p><code>divide dup</code>, which duplicates input in order to feed each of its arguments, is a combinator worthy of a name, or even two:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ot">dplus ::</span> <span class="dt">Divisible</span> k <span class="ot">=></span> k a <span class="ot">-></span> k a <span class="ot">-></span> k a</span>
<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a>dplus <span class="ot">=</span> divide dup</span>
<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="ot">(>+<) ::</span> <span class="dt">Divisible</span> k <span class="ot">=></span> k a <span class="ot">-></span> k a <span class="ot">-></span> k a</span>
<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a>(<span class="op">>+<</span>) <span class="ot">=</span> dplus</span>
<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="op">>+<</span></span></code></pre></div>
<p>So we have:</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>tdivide f g u v <span class="ot">=</span> dplus (contramap f u) (contramap g v)</span></code></pre></div>
<p>Or, using the operators:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>tdivide f g u v <span class="ot">=</span> f <span class="op">>$<</span> u <span class="op">>+<</span> g <span class="op">>$<</span> v</span></code></pre></div>
<p>An alternative to using the projections to set up a deconstructor to be used with <code>divide</code> is to contramap each projection to its corresponding divisible value and combine the pieces with <code>(>+<)</code>. That is the style favoured by Tom Ellis, <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> which is why I have added a “t” prefix to <code>tdivide</code> comes from. For instance, Gabriella Gonzalez’s example would be spelled as follows in this style:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="ot">nonNegativeOctantT ::</span> <span class="dt">Predicate</span> <span class="dt">Point</span></span>
<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a>nonNegativeOctantT <span class="ot">=</span></span>
<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> x <span class="op">>$<</span> nonNegative <span class="op">>+<</span> y <span class="op">>$<</span> nonNegative <span class="op">>+<</span> z <span class="op">>$<</span> nonNegative</span></code></pre></div>
<h2 id="alternative">Alternative</h2>
<p>The <code>(>+<)</code> combinator defined above is strikingly similar to <code>(<|>)</code> from <code>Alternative</code>, down to its implied monoidal nature: <a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a></p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(>+<) ::</span> <span class="dt">Divisible</span> k <span class="ot">=></span> k a <span class="ot">-></span> k a <span class="ot">-></span> k a</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="ot">(<|>) ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> f a <span class="ot">-></span> f a <span class="ot">-></span> f a</span></code></pre></div>
<p>It is surprising that <code>(>+<)</code> springs forth in <code>Divisible</code> rather than <code>Decidable</code>, which might look like the more obvious candidate to be <code>Alternative</code>’s contravariant counterpart. To understand what is going on, it helps to look at <code>Alternative</code> from the same perspective we have used here for <code>Applicative</code> and <code>Divisible</code>. For that, first of all we need an analogue to <code>divided</code>. Let’s borrow the definition from <em>Applicatives convert products to sums</em>:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="ot">combined ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f (<span class="dt">Either</span> a b)</span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>combined u v <span class="ot">=</span> <span class="dt">Left</span> <span class="op"><$></span> u <span class="op"><|></span> <span class="dt">Right</span> <span class="op"><$></span> v</span>
<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="ot">(-|-) ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f (<span class="dt">Either</span> a b)</span>
<span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a>(<span class="op">-|-</span>) <span class="ot">=</span> combined</span>
<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="op">-|-</span></span>
<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- We also need a suitable identity:</span></span>
<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="ot">zero ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> f <span class="dt">Void</span></span>
<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a>zero <span class="ot">=</span> empty</span>
<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a><span class="co">-- Laws:</span></span>
<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="co">-- zero -|- v ~ v</span></span>
<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="co">-- u -|- zero ~ u</span></span>
<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="co">-- (u -|- v) -|- w ~ u -|- (v -|- w)</span></span></code></pre></div>
<p>(I won’t entertain the various controversies about the <code>Alternative</code> laws here, nor any interaction laws involving <code>Applicative</code>. Those might be interesting matters to think about from this vantage point, though.)</p>
<p>A <code>divide</code> analogue follows:</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="ot">combine ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> (<span class="dt">Either</span> a b <span class="ot">-></span> c) <span class="ot">-></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f c</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>combine f u v <span class="ot">=</span> <span class="fu">fmap</span> f (combined u v)</span></code></pre></div>
<p>Crucially, <code>Either a b -> c</code> can be split in a way dual to what we have seen earlier with <code>a -> (b, c)</code>: an <code>Either</code>-consuming function amounts to a pair of functions, one to deal with each component. That being so, we can use the alternative style trick done for <code>Divisible</code> by dualising things:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="ot">tcombine ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> (a <span class="ot">-></span> c) <span class="ot">-></span> (b <span class="ot">-></span> c) <span class="ot">-></span> f a <span class="ot">-></span> f b <span class="ot">-></span> f c</span>
<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a>tcombine f g <span class="ot">=</span> combine (f <span class="op">|||</span> g)</span></code></pre></div>
<div class="sourceCode" id="cb19"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a>tcombine f g u v</span>
<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a>combine (f <span class="op">|||</span> g) u v</span>
<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> (f <span class="op">|||</span> g) (combined u v)</span>
<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> (forget <span class="op">.</span> (f <span class="op">+++</span> g)) (combined u v)</span>
<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> forget (combined (<span class="fu">fmap</span> f u) (<span class="fu">fmap</span> g v))</span>
<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a>combine forget (<span class="fu">fmap</span> f u) (<span class="fu">fmap</span> g v)</span></code></pre></div>
<p>To keep things symmetrical, let’s define:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="ot">aplus ::</span> <span class="dt">Alternative</span> f <span class="ot">=></span> f a <span class="ot">-></span> f a <span class="ot">-></span> f a</span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a>aplus <span class="ot">=</span> combine forget</span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="co">-- (<|>) = aplus</span></span></code></pre></div>
<p>So that we end up with:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>tcombine f g u v <span class="ot">=</span> aplus (<span class="fu">fmap</span> f u) (<span class="fu">fmap</span> g v)</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>tcombine f g u v <span class="ot">=</span> f <span class="op"><$></span> u <span class="op"><|></span> g <span class="op"><$></span> v</span></code></pre></div>
<p>For instance, here is the <code>Alternative</code> composition example from the <em>Decidable</em> post…</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="ot">alternativeCompose ::</span> [<span class="dt">String</span>]</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a>alternativeCompose <span class="ot">=</span> <span class="fu">show</span> <span class="op"><$></span> [<span class="dv">1</span>,<span class="dv">2</span>] <span class="op"><|></span> <span class="fu">reverse</span> <span class="op"><$></span> [<span class="st">"hello"</span>, <span class="st">"world"</span>]</span></code></pre></div>
<p>… and how it might be rendered using <code>combine</code>/<code>(-|-)</code>:</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="ot">alternativeComposeG ::</span> [<span class="dt">String</span>]</span>
<span id="cb23-2"><a href="#cb23-2" aria-hidden="true" tabindex="-1"></a>alternativeComposeG <span class="ot">=</span> merge <span class="op"><$></span> [<span class="dv">1</span>,<span class="dv">2</span>] <span class="op">-|-</span> [<span class="st">"hello"</span>, <span class="st">"world"</span>]</span>
<span id="cb23-3"><a href="#cb23-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a> merge <span class="ot">=</span> <span class="fu">show</span> <span class="op">|||</span> <span class="fu">reverse</span></span></code></pre></div>
<p>There is, therefore, something of a subterranean connection between <code>Alternative</code> and <code>Divisible</code>. The function arguments to both <code>combine</code> and <code>divide</code>, whose types are dual to each other, can be split in a way that not only reveals an underlying monoidal operation, <code>(<|>)</code> and <code>(>+<)</code> respectively, but also allows for a certain flexibility in using the class combinators.</p>
<h2 id="decidable">Decidable</h2>
<p>Last, but not least, there is <code>Decidable</code> to deal with. <code>Data.Functor.Contravariant.Divisible</code> already provides <code>chosen</code> as the <code>divided</code> analogue, so let’s just supply the and operator variant: <a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a></p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="ot">(|-|) ::</span> <span class="dt">Decidable</span> k <span class="ot">=></span> k a <span class="ot">-></span> k b <span class="ot">-></span> k (<span class="dt">Either</span> a b)</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>(<span class="op">|-|</span>) <span class="ot">=</span> chosen</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="kw">infixr</span> <span class="dv">5</span> <span class="op">|-|</span></span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-5"><a href="#cb24-5" aria-hidden="true" tabindex="-1"></a><span class="co">-- Laws:</span></span>
<span id="cb24-6"><a href="#cb24-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb24-7"><a href="#cb24-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- lost |-| v ~ v</span></span>
<span id="cb24-8"><a href="#cb24-8" aria-hidden="true" tabindex="-1"></a><span class="co">-- u |-| lost ~ u</span></span>
<span id="cb24-9"><a href="#cb24-9" aria-hidden="true" tabindex="-1"></a><span class="co">-- (u |-| v) |-| w ~ u |-| (v |-| w)</span></span></code></pre></div>
<p><code>choose</code> can be recovered from <code>chosen</code> in the usual way:</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="ot">choose ::</span> <span class="dt">Decidable</span> k <span class="ot">=></span> (a <span class="ot">-></span> <span class="dt">Either</span> b c) <span class="ot">-></span> k b <span class="ot">-></span> k c <span class="ot">-></span> k a</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>choose f u v <span class="ot">=</span> contamap f (chosen u v)</span></code></pre></div>
<p>The <code>a -> Either b c</code> argument of <code>choose</code>, however, is not amenable to the function splitting trick we have used for <code>divide</code> and <code>combine</code>. <code>Either</code>-producing functions cannot be decomposed in that manner, as the case analysis to decide whether to return <code>Left</code> or <code>Right</code> cannot be disentangled. This is ultimately what Tom’s complaint about the “mysterious incomposability” of <code>Decidable</code> is about. Below is a paraphrased version of the <code>Decidable</code> example from the <em>Decidable</em> post:</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Foo</span> <span class="ot">=</span> <span class="dt">Bar</span> <span class="dt">String</span> <span class="op">|</span> <span class="dt">Baz</span> <span class="dt">Bool</span> <span class="op">|</span> <span class="dt">Quux</span> <span class="dt">Int</span></span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> <span class="dt">Show</span></span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a><span class="ot">pString ::</span> <span class="dt">Predicate</span> <span class="dt">String</span></span>
<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a>pString <span class="ot">=</span> <span class="dt">Predicate</span> (<span class="fu">const</span> <span class="dt">False</span>)</span>
<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a><span class="ot">pBool ::</span> <span class="dt">Predicate</span> <span class="dt">Bool</span></span>
<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a>pBool <span class="ot">=</span> <span class="dt">Predicate</span> <span class="fu">id</span></span>
<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="ot">pInt ::</span> <span class="dt">Predicate</span> <span class="dt">Int</span></span>
<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a>pInt <span class="ot">=</span> <span class="dt">Predicate</span> (<span class="op">>=</span> <span class="dv">0</span>)</span>
<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a><span class="ot">decidableCompose ::</span> <span class="dt">Predicate</span> <span class="dt">Foo</span></span>
<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a>decidableCompose <span class="ot">=</span> analyse <span class="op">>$<</span> pString <span class="op">|-|</span> pBool <span class="op">|-|</span> pInt</span>
<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb26-16"><a href="#cb26-16" aria-hidden="true" tabindex="-1"></a> analyse <span class="ot">=</span> \<span class="kw">case</span></span>
<span id="cb26-17"><a href="#cb26-17" aria-hidden="true" tabindex="-1"></a> <span class="dt">Bar</span> s <span class="ot">-></span> <span class="dt">Left</span> s</span>
<span id="cb26-18"><a href="#cb26-18" aria-hidden="true" tabindex="-1"></a> <span class="dt">Baz</span> b <span class="ot">-></span> <span class="dt">Right</span> (<span class="dt">Left</span> b)</span>
<span id="cb26-19"><a href="#cb26-19" aria-hidden="true" tabindex="-1"></a> <span class="dt">Quux</span> n <span class="ot">-></span> <span class="dt">Right</span> (<span class="dt">Right</span> n)</span></code></pre></div>
<p>The problem identified in the post is that there is no straightfoward way around having to write “the explicit unpacking into an <code>Either</code>” performed by <code>analyse</code>. In the <code>Divisible</code> and <code>Alternative</code> examples, it was possible to avoid tuple or <code>Either</code> shuffling by decomposing the counterparts to <code>analyse</code>, but that is not possible here. <a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a></p>
<p>In the last few paragraphs, we have mentioned <code>Divisible</code>, <code>Alternative</code> and <code>Decidable</code>. What about <code>Applicative</code>, though? The <code>Applicative</code> example from the <em>Decidable</em> post is written in the usual applicative style:</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="ot">applicativeCompose ::</span> [[<span class="dt">String</span>]]</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>applicativeCompose <span class="ot">=</span></span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a> f <span class="op"><$></span> [<span class="dv">1</span>, <span class="dv">2</span>] <span class="op"><*></span> [<span class="dt">True</span>, <span class="dt">False</span>] <span class="op"><*></span> [<span class="st">"hello"</span>, <span class="st">"world"</span>]</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb27-5"><a href="#cb27-5" aria-hidden="true" tabindex="-1"></a> f <span class="ot">=</span> (\a b c <span class="ot">-></span> <span class="fu">replicate</span> a (<span class="kw">if</span> b <span class="kw">then</span> c <span class="kw">else</span> <span class="st">"False"</span>))</span></code></pre></div>
<p>As noted earlier, though, applicative style is a fortunate consequence of <strong>Hask</strong> being Cartesian closed, which makes it possible to turn <code>(a, b) -> c</code> into <code>a -> b -> c</code>. If we leave out <code>(<*>)</code> and restrict ourselves to <code>(&*&)</code>, we end up having to deal explicitly with tuples, which is a dual version of the <code>Decidable</code> issue:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="ot">monoidalCompose ::</span> [[<span class="dt">String</span>]]</span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>monoidalCompose <span class="ot">=</span></span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a> consume <span class="op"><$></span> [<span class="dv">1</span>, <span class="dv">2</span>] <span class="op">&*&</span> [<span class="dt">True</span>, <span class="dt">False</span>] <span class="op">&*&</span> [<span class="st">"hello"</span>, <span class="st">"world"</span>]</span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> consume (a, (b, c)) <span class="ot">=</span> <span class="fu">replicate</span> a (<span class="kw">if</span> b <span class="kw">then</span> c <span class="kw">else</span> <span class="st">"False"</span>)</span></code></pre></div>
<p>Just like <code>a -> Either b c</code> functions, <code>(a, b) -> c</code> functions cannot be decomposed: the <code>c</code> value can be produced by using the <code>a</code> and <code>b</code> components in arbitrary ways, and there is no easy way to disentangle that.</p>
<p><code>Decidable</code>, then, relates to <code>Applicative</code> in an analogous way to how <code>Divisible</code> does to <code>Alternative</code>. There are a few other similarities between them that are worth pointing out:</p>
<ul>
<li><p>Neither <code>Applicative</code> nor <code>Decidable</code> offer a monoidal <code>f a -> f a -> f a</code> operation like the ones of <code>Alternative</code> and <code>Decidable</code>. A related observation is that, for example, <code>Op</code>’s <code>Decidable</code> instance inherits a <code>Monoid</code> constraint from <code>Divisible</code> but doesn’t actually use it in the method implementations.</p></li>
<li><p><code>choose Left</code> and <code>choose Right</code> can be used to combine consumers so that one of them doesn’t actually receive input. That is analogous to how <code>(<*) = lizip fst</code> and <code>(*>) = lizip snd</code> combine applicative values while discarding the output from one of them.</p></li>
<li><p>Dually to how <code>zipped</code>/<code>&*&</code> for the function functor is <code>(&&&)</code>, <code>chosen</code> for decidables such as <code>Op</code> and <code>Predicate</code> amounts to <code>(|||)</code>. My choice of <code>|-|</code> as the corresponding operator hints at that.</p></li>
</ul>
<h2 id="in-summary">In summary</h2>
<p>To wrap things up, here is a visual summary of the parallels between the four classes:</p>
<figure>
<img src="../images/posts/divisible-and-the-monoidal-quartet/monoidal-quartet-diagram.png" alt="Diagram of the four monoidal functor classes under consideration, with Applicative and Decidable in one diagonal, and Alternative and Divisible in the other." /><figcaption aria-hidden="true"><em>Diagram of the four monoidal functor classes under consideration, with <code>Applicative</code> and <code>Decidable</code> in one diagonal, and <code>Alternative</code> and <code>Divisible</code> in the other.</em></figcaption>
</figure>
<p>To my eyes, the main takeaway of our figure of eight trip around this diagram has to do with its diagonals. Thanks to a peculiar kind of duality, classes in opposite corners of it are similar to each other in quite a few ways. In particular, the orange diagonal classes, <code>Alternative</code> and <code>Divisible</code>, have monoidal operations of <code>f a -> f a -> f a</code> signature that emerge from their monoidal functor structure.</p>
<p>That <code>Divisible</code>, from this perspective, appears to have more to do with <code>Alternative</code> than with <code>Applicative</code> leaves us a question to ponder: what does that mean for the relationship between <code>Divisible</code> and <code>Decidable</code>? The current class hierarchy, with <code>Decidable</code> being a subclass of <code>Divisible</code>, mirrors the <code>Alternative</code>-<code>Applicative</code> relationship on the other side of the covariant-contravariant divide. That, however, is not the only reasonable arrangement, and possibly not even the most natural one. <a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a></p>
<h2 id="appendixes">Appendixes</h2>
<h3 id="dplus-is-a-monoidal-operation">dplus is a monoidal operation</h3>
<p>If we are to show that <code>(>+<)</code> is a monoidal operation, first of all we need an identity for it. <code>conquer :: f a</code> sounds like a reasonable candidate. It can be expressed in terms of <code>conquered</code>, the unit for <code>divided</code>, as follows:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- conquer discards input.</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a>conquer <span class="ot">=</span> <span class="fu">const</span> () <span class="op">>$<</span> conquered</span></code></pre></div>
<p>The identity laws do come out all right:</p>
<div class="sourceCode" id="cb30"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a>conquer <span class="op">>+<</span> v <span class="ot">=</span> v <span class="co">-- Goal</span></span>
<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>conquer <span class="op">>+<</span> v <span class="co">-- LHS</span></span>
<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (conquer <span class="op">>*<</span> v)</span>
<span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> ((<span class="fu">const</span> () <span class="op">>$<</span> conquered) <span class="op">>*<</span> v)</span>
<span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (first (<span class="fu">const</span> ()) <span class="op">>$<</span> (conquered <span class="op">>*<</span> v))</span>
<span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>first (<span class="fu">const</span> ()) <span class="op">.</span> dup <span class="op">>$<</span> (conquered <span class="op">>*<</span> v)</span>
<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a><span class="co">-- conquered >*< v ~ v</span></span>
<span id="cb30-8"><a href="#cb30-8" aria-hidden="true" tabindex="-1"></a>first (<span class="fu">const</span> ()) <span class="op">.</span> dup <span class="op">>$<</span> (<span class="fu">snd</span> <span class="op">>$<</span> v)</span>
<span id="cb30-9"><a href="#cb30-9" aria-hidden="true" tabindex="-1"></a><span class="fu">snd</span> <span class="op">.</span> first (<span class="fu">const</span> ()) <span class="op">.</span> dup <span class="op">>$<</span> v</span>
<span id="cb30-10"><a href="#cb30-10" aria-hidden="true" tabindex="-1"></a>v <span class="co">-- LHS = RHS</span></span>
<span id="cb30-11"><a href="#cb30-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb30-12"><a href="#cb30-12" aria-hidden="true" tabindex="-1"></a>u <span class="op">>+<</span> conquer <span class="ot">=</span> u <span class="co">-- Goal</span></span>
<span id="cb30-13"><a href="#cb30-13" aria-hidden="true" tabindex="-1"></a>u <span class="op">>+<</span> conquer <span class="co">-- LHS</span></span>
<span id="cb30-14"><a href="#cb30-14" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (u <span class="op">>*<</span> discard)</span>
<span id="cb30-15"><a href="#cb30-15" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (u <span class="op">>*<</span> (<span class="fu">const</span> () <span class="op">>$<</span> conquered))</span>
<span id="cb30-16"><a href="#cb30-16" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (second (<span class="fu">const</span> ()) <span class="op">>$<</span> (u <span class="op">>*<</span> conquered))</span>
<span id="cb30-17"><a href="#cb30-17" aria-hidden="true" tabindex="-1"></a>second (<span class="fu">const</span> ()) <span class="op">.</span> dup <span class="op">>$<</span> (u <span class="op">>*<</span> conquered)</span>
<span id="cb30-18"><a href="#cb30-18" aria-hidden="true" tabindex="-1"></a><span class="co">-- u >*< conquered ~ u</span></span>
<span id="cb30-19"><a href="#cb30-19" aria-hidden="true" tabindex="-1"></a>second (<span class="fu">const</span> ()) <span class="op">.</span> dup <span class="op">>$<</span> (<span class="fu">fst</span> <span class="op">>$<</span> u)</span>
<span id="cb30-20"><a href="#cb30-20" aria-hidden="true" tabindex="-1"></a><span class="fu">fst</span> <span class="op">.</span> second (<span class="fu">const</span> ()) <span class="op">.</span> dup <span class="op">>$<</span> u</span>
<span id="cb30-21"><a href="#cb30-21" aria-hidden="true" tabindex="-1"></a>u <span class="co">-- LHS = RHS</span></span></code></pre></div>
<p>And so does the associativity one:</p>
<div class="sourceCode" id="cb31"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a>(u <span class="op">>+<</span> v) <span class="op">>+<</span> w <span class="ot">=</span> u <span class="op">>+<</span> (v <span class="op">>+<</span> w) <span class="co">-- Goal</span></span>
<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a>(u <span class="op">>+<</span> v) <span class="op">>+<</span> w <span class="co">-- LHS</span></span>
<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> ((dup <span class="op">>$<</span> (u <span class="op">>*<</span> v)) <span class="op">>*<</span> w)</span>
<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (first dup <span class="op">>$<</span> ((u <span class="op">>*<</span> v) <span class="op">>*<</span> w))</span>
<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a>first dup <span class="op">.</span> dup <span class="op">>$<</span> ((u <span class="op">>*<</span> v) <span class="op">>*<</span> w)</span>
<span id="cb31-6"><a href="#cb31-6" aria-hidden="true" tabindex="-1"></a>u <span class="op">>+<</span> (v <span class="op">>+<</span> w) <span class="co">-- RHS</span></span>
<span id="cb31-7"><a href="#cb31-7" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (u <span class="op">>*<</span> (dup <span class="op">>$<</span> (v <span class="op">>*<</span> w)))</span>
<span id="cb31-8"><a href="#cb31-8" aria-hidden="true" tabindex="-1"></a>dup <span class="op">>$<</span> (second dup <span class="op">>$<</span> (u <span class="op">>*<</span> (v <span class="op">>*<</span> w)))</span>
<span id="cb31-9"><a href="#cb31-9" aria-hidden="true" tabindex="-1"></a>second dup <span class="op">.</span> dup <span class="op">>$<</span> (u <span class="op">>*<</span> (v <span class="op">>*<</span> w))</span>
<span id="cb31-10"><a href="#cb31-10" aria-hidden="true" tabindex="-1"></a><span class="co">-- (u >*< v) >*< w ~ u >*< (v >*< w)</span></span>
<span id="cb31-11"><a href="#cb31-11" aria-hidden="true" tabindex="-1"></a><span class="co">-- assoc ((x, y), z) = (x, (y, z))</span></span>
<span id="cb31-12"><a href="#cb31-12" aria-hidden="true" tabindex="-1"></a>second dup <span class="op">.</span> dup <span class="op">>$<</span> (assoc <span class="op">>$<</span> ((u <span class="op">>*<</span> v) <span class="op">>*<</span> w))</span>
<span id="cb31-13"><a href="#cb31-13" aria-hidden="true" tabindex="-1"></a>assoc <span class="op">.</span> second dup <span class="op">.</span> dup <span class="op">>$<</span> ((u <span class="op">>*<</span> v) <span class="op">>*<</span> w)</span>
<span id="cb31-14"><a href="#cb31-14" aria-hidden="true" tabindex="-1"></a>first dup <span class="op">.</span> dup <span class="op">>$<</span> ((u <span class="op">>*<</span> v) <span class="op">>*<</span> w) <span class="co">-- LHS = RHS</span></span></code></pre></div>
<h3 id="handling-nested-either">Handling nested Either</h3>
<p><em>The examples in this appendix are available as <a href="../demos/Quartet/Appendix.hs">a separate <code>.hs</code> file</a>.</em></p>
<p>There is a certain awkwardness in dealing with nested <code>Either</code> as anonymous sums that is hard to get rid of completely. Prisms are a tool worth looking into in this context, as they are largely about expressing pattern matching in a composable way. Let’s bring <em>lens</em> into Tom’s <code>Decidable</code> example, then:</p>
<div class="sourceCode" id="cb32"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Foo</span> <span class="ot">=</span> <span class="dt">Bar</span> <span class="dt">String</span> <span class="op">|</span> <span class="dt">Baz</span> <span class="dt">Bool</span> <span class="op">|</span> <span class="dt">Quux</span> <span class="dt">Int</span></span>
<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>)</span>
<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a>makePrisms '<span class="dt">'Foo</span></span></code></pre></div>
<p>A cute trick with prisms is using <a href="https://hackage.haskell.org/package/lens-5.0.1/docs/Control-Lens-Prism.html#v:outside"><code>outside</code></a> to fill in the missing cases of a partial function (in this case, <code>(^?! _Quux)</code>:</p>
<div class="sourceCode" id="cb33"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="ot">anonSum ::</span> <span class="dt">APrism'</span> s a <span class="ot">-></span> (s <span class="ot">-></span> b) <span class="ot">-></span> s <span class="ot">-></span> <span class="dt">Either</span> a b</span>
<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a>anonSum p cases <span class="ot">=</span> set (outside p) <span class="dt">Left</span> (<span class="dt">Right</span> <span class="op">.</span> cases)</span>
<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a><span class="ot">decidableOutside ::</span> <span class="dt">Predicate</span> <span class="dt">Foo</span></span>
<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a>decidableOutside <span class="ot">=</span> analyse <span class="op">>$<</span> pString <span class="op">|-|</span> pBool <span class="op">|-|</span> pInt</span>
<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">where</span></span>
<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a> analyse <span class="ot">=</span> _Bar <span class="ot">`anonSum`</span> (_Baz <span class="ot">`anonSum`</span> (<span class="op">^?!</span> _Quux))</span></code></pre></div>
<p>An alternative is using <a href="https://hackage.haskell.org/package/lens-5.0.1/docs/Control-Lens-Prism.html#v:matching"><code>matching</code></a> to write it in a more self-explanatory way:</p>
<div class="sourceCode" id="cb34"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="ot">matchingL ::</span> <span class="dt">APrism'</span> s a <span class="ot">-></span> s <span class="ot">-></span> <span class="dt">Either</span> a s</span>
<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a>matchingL p <span class="ot">=</span> view swapped <span class="op">.</span> matching p</span>
<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a><span class="ot">decidableMatching ::</span> <span class="dt">Predicate</span> <span class="dt">Foo</span></span>
<span id="cb34-5"><a href="#cb34-5" aria-hidden="true" tabindex="-1"></a>decidableMatching <span class="ot">=</span></span>
<span id="cb34-6"><a href="#cb34-6" aria-hidden="true" tabindex="-1"></a> choose (matchingL _Bar) pString <span class="op">$</span></span>
<span id="cb34-7"><a href="#cb34-7" aria-hidden="true" tabindex="-1"></a> choose (matchingL _Baz) pBool <span class="op">$</span></span>
<span id="cb34-8"><a href="#cb34-8" aria-hidden="true" tabindex="-1"></a> choose (matchingL _Quux) pInt <span class="op">$</span></span>
<span id="cb34-9"><a href="#cb34-9" aria-hidden="true" tabindex="-1"></a> <span class="fu">error</span> <span class="st">"Missing case in decidableMatching"</span></span></code></pre></div>
<p>These implementations have a few inconveniences of their own, the main one perhaps being that there is noting to stop us from forgetting one of the prisms. The combinators from <a href="https://hackage.haskell.org/package/total-1.0.6">the <em>total</em> package</a> improve on that by incorporating exhaustiveness checking for prisms, at the cost of requiring the sum type to be defined in a particular way.</p>
<p>There presumably also is the option of brining in heavy machinery, and setting up an anonymous sum wrangler with Template Haskell or generics. In fact, it appears <a href="https://hackage.haskell.org/package/shapely-data">the <em>shapely-data</em> package</a> used to offer precisely that. It might be worth it to take a moment to make it build with recent GHCs.</p>
<p>All in all, these approaches feel like attempts to approximate extra language support for juggling sum types. As it happens, though, there is a corner of the language which does provide extra support: <a href="https://downloads.haskell.org/ghc/9.2.1/docs/html/users_guide/exts/arrows.html#conditional-commands">arrow notation</a>. Converting the example to arrows provides a glimpse of what might be:</p>
<div class="sourceCode" id="cb35"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb35-1"><a href="#cb35-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- I'm going to play nice, rather than making b phantom and writing a</span></span>
<span id="cb35-2"><a href="#cb35-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- blatantly unlawful Arrow instance just for the sake of the notation.</span></span>
<span id="cb35-3"><a href="#cb35-3" aria-hidden="true" tabindex="-1"></a><span class="kw">newtype</span> <span class="dt">Pipecate</span> a b <span class="ot">=</span> <span class="dt">Pipecate</span> {<span class="ot"> getPipecate ::</span> a <span class="ot">-></span> (<span class="dt">Bool</span>, b) }</span>
<span id="cb35-4"><a href="#cb35-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-5"><a href="#cb35-5" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Category</span> <span class="dt">Pipecate</span> <span class="kw">where</span></span>
<span id="cb35-6"><a href="#cb35-6" aria-hidden="true" tabindex="-1"></a> <span class="fu">id</span> <span class="ot">=</span> <span class="dt">Pipecate</span> (<span class="dt">True</span>,)</span>
<span id="cb35-7"><a href="#cb35-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">Pipecate</span> q <span class="op">.</span> <span class="dt">Pipecate</span> p <span class="ot">=</span> <span class="dt">Pipecate</span> <span class="op">$</span> \x <span class="ot">-></span></span>
<span id="cb35-8"><a href="#cb35-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> (bx, y) <span class="ot">=</span> p x</span>
<span id="cb35-9"><a href="#cb35-9" aria-hidden="true" tabindex="-1"></a> (by, z) <span class="ot">=</span> q y</span>
<span id="cb35-10"><a href="#cb35-10" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span> (bx <span class="op">&&</span> by, z)</span>
<span id="cb35-11"><a href="#cb35-11" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-12"><a href="#cb35-12" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Arrow</span> <span class="dt">Pipecate</span> <span class="kw">where</span></span>
<span id="cb35-13"><a href="#cb35-13" aria-hidden="true" tabindex="-1"></a> arr f <span class="ot">=</span> <span class="dt">Pipecate</span> (<span class="fu">const</span> <span class="dt">True</span> <span class="op">&&&</span> f)</span>
<span id="cb35-14"><a href="#cb35-14" aria-hidden="true" tabindex="-1"></a> first (<span class="dt">Pipecate</span> p) <span class="ot">=</span> <span class="dt">Pipecate</span> <span class="op">$</span> \(x, o) <span class="ot">-></span></span>
<span id="cb35-15"><a href="#cb35-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> (bx, y) <span class="ot">=</span> p x</span>
<span id="cb35-16"><a href="#cb35-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span> (bx, (y, o))</span>
<span id="cb35-17"><a href="#cb35-17" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-18"><a href="#cb35-18" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">ArrowChoice</span> <span class="dt">Pipecate</span> <span class="kw">where</span></span>
<span id="cb35-19"><a href="#cb35-19" aria-hidden="true" tabindex="-1"></a> left (<span class="dt">Pipecate</span> p) <span class="ot">=</span> <span class="dt">Pipecate</span> <span class="op">$</span> \<span class="kw">case</span></span>
<span id="cb35-20"><a href="#cb35-20" aria-hidden="true" tabindex="-1"></a> <span class="dt">Left</span> x <span class="ot">-></span></span>
<span id="cb35-21"><a href="#cb35-21" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> (bx, y) <span class="ot">=</span> p x</span>
<span id="cb35-22"><a href="#cb35-22" aria-hidden="true" tabindex="-1"></a> <span class="kw">in</span> (bx, <span class="dt">Left</span> y)</span>
<span id="cb35-23"><a href="#cb35-23" aria-hidden="true" tabindex="-1"></a> <span class="dt">Right</span> o <span class="ot">-></span> (<span class="dt">True</span>, <span class="dt">Right</span> o)</span>
<span id="cb35-24"><a href="#cb35-24" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-25"><a href="#cb35-25" aria-hidden="true" tabindex="-1"></a><span class="ot">fromPred ::</span> <span class="dt">Predicate</span> a <span class="ot">-></span> <span class="dt">Pipecate</span> a ()</span>
<span id="cb35-26"><a href="#cb35-26" aria-hidden="true" tabindex="-1"></a>fromPred (<span class="dt">Predicate</span> p) <span class="ot">=</span> <span class="dt">Pipecate</span> (p <span class="op">&&&</span> <span class="fu">const</span> ())</span>
<span id="cb35-27"><a href="#cb35-27" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-28"><a href="#cb35-28" aria-hidden="true" tabindex="-1"></a><span class="ot">toPred ::</span> <span class="dt">Pipecate</span> a x <span class="ot">-></span> <span class="dt">Predicate</span> a</span>
<span id="cb35-29"><a href="#cb35-29" aria-hidden="true" tabindex="-1"></a>toPred (<span class="dt">Pipecate</span> p) <span class="ot">=</span> <span class="dt">Predicate</span> (<span class="fu">fst</span> <span class="op">.</span> p)</span>
<span id="cb35-30"><a href="#cb35-30" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb35-31"><a href="#cb35-31" aria-hidden="true" tabindex="-1"></a><span class="ot">decidableArrowised ::</span> <span class="dt">Predicate</span> <span class="dt">Foo</span></span>
<span id="cb35-32"><a href="#cb35-32" aria-hidden="true" tabindex="-1"></a>decidableArrowised <span class="ot">=</span> toPred <span class="op">$</span> proc foo <span class="ot">-></span> <span class="kw">case</span> foo <span class="kw">of</span></span>
<span id="cb35-33"><a href="#cb35-33" aria-hidden="true" tabindex="-1"></a> <span class="dt">Bar</span> s <span class="ot">-></span> fromPred pString <span class="op">-<</span> s</span>
<span id="cb35-34"><a href="#cb35-34" aria-hidden="true" tabindex="-1"></a> <span class="dt">Baz</span> b <span class="ot">-></span> fromPred pBool <span class="op">-<</span> b</span>
<span id="cb35-35"><a href="#cb35-35" aria-hidden="true" tabindex="-1"></a> <span class="dt">Quux</span> n <span class="ot">-></span> fromPred pInt <span class="op">-<</span> n</span></code></pre></div>
<p><code>decidableArrowised</code> corresponds quite closely to the various <code>Decidable</code>-powered implementations. Behind the scenes, <code>case</code> commands in arrow notation give rise to nested eithers. Said eithers are dealt with by the arrows, which are combined in an appropriate way with <code>(|||)</code>. <code>(|||)</code>, in turn, can be seen as an arrow counterpart to <code>chosen</code>/<code>(|-|)</code>. Even the <code>-<</code> “feed” syntax, which the example above doesn’t really take advantage of, amounts to slots for contramapping. If someone ever feels like arranging a do-esque noation for <code>Decidable</code> to go with Gabriella’s <code>DivisibleFrom</code>, it seems <code>case</code> commands would be a nice starting point.</p>
<section class="footnotes footnotes-end-of-document" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>See <a href="https://wiki.haskell.org/Typeclassopedia#Alternative_formulation">the relevant section of the <em>Typeclassopedia</em></a> for a brief explanation of it.<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>See, for instance, <a href="https://twitter.com/tomjaguarpaw/status/1451235378363609096">this Twitter conversation</a>, or the <code>Divisible</code> example in the <em>Decidable</em> post. Note that, though I’m using <code>(>$<)</code> here for ease of comparison, the examples in this style arguably look tidier when spelled with <code>contramap</code>.</p>
<p>Speaking of operator usage, it is not straightforward to decide on the right fixities for all those operators, and it is entirely possible that I have overlooked something. I have picked them aiming to have both styles work without parentheses, and to have the pairs associated to the right, that is:</p>
<div class="sourceCode" id="cb13"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a>adapt <span class="op">>$<</span> u <span class="op">>*<</span> v <span class="op">>*<</span> w</span>
<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> adapt <span class="op">>$<</span> (u <span class="op">>*<</span> (v <span class="op">>*<</span> w))</span>
<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a>f <span class="op">>$<</span> u <span class="op">>+<</span> g <span class="op">>$<</span> v <span class="op">>+<</span> h <span class="op">>$<</span> v</span>
<span id="cb13-5"><a href="#cb13-5" aria-hidden="true" tabindex="-1"></a> <span class="ot">=</span> (f <span class="op">>$<</span> u) <span class="op">>+<</span> (g <span class="op">>$<</span> v) <span class="op">>+<</span> (h <span class="op">>$<</span> w)</span></code></pre></div>
<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></li>
<li id="fn3" role="doc-endnote"><p>A proof that <code>(>+<)</code> is indeed monoidal is in <a href="#dplus-is-a-monoidal-operation">an end note</a> to this post.</p>
<p>On a related note, my choice of <code>>+<</code> as the <code>dplus</code> operator is, in part, a pun on <a href="https://hackage.haskell.org/package/base-4.16.0.0/docs/Control-Arrow.html#t:ArrowPlus"><code>(<+>)</code> from <code>ArrowPlus</code></a>. <code>(>+<)</code> for many instances works very much like <code>(<+>)</code>, monoidally combining outputs, even if there probably isn’t a sensible way to actually make the types underlying the various <code>Divisible</code> functors instances of <code>ArrowPlus</code>.<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn4" role="doc-endnote"><p>Both <a href="https://hackage.haskell.org/package/dhall-1.40.1/docs/Dhall-Marshal-Encode.html#v:-62--124--60-"><em>dhall</em></a> and <a href="https://hackage.haskell.org/package/co-log-core-0.3.0.0/docs/Colog-Core-Action.html#v:-62--124--60-"><em>co-log-core</em></a> define <code>(>|<)</code> as <code>chosen</code>-like operators. To my eyes, though, <code>>|<</code> fits <code>dplus</code> better. As a compromise, I opted to not use <code>>|<</code> for neither of them here.<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn5" role="doc-endnote"><p>I will play with a couple of approaches to nested <code>Either</code> ergonomics at the end of the post, in an appendix.<a href="#fnref5" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn6" role="doc-endnote"><p>See also <a href="https://github.com/ekmett/contravariant/issues/64"><em>contravariant</em> issue #64</a>, which suggests no longer making <code>Decidable</code> a subclass of <code>Divisible</code>. Though the argument made by Zemyla is a different one, there are resonances with the observations made here. On a related development, <em>semigroupoids</em> has recently introduced <a href="https://hackage.haskell.org/package/semigroupoids-5.3.6/docs/Data-Functor-Contravariant-Conclude.html">a <code>Conclude</code> class</a>, which amounts to “<code>Decidable</code> without a superclass constraint on <code>Divisible</code>”.<a href="#fnref6" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
<div id="comment-nav" class="pure-g-r no-print">
<div class="pure-u-1-4">
<a id="gh-comments-button" class="pure-button" href="https://github.com/duplode/duplode.github.io/issues/16">Comment on GitHub</a>
</div>
<div class="pure-u-1-4">
</div>
<div class="pure-u-1-4">
<a id="discourse-button" class="pure-button" href="https://discourse.haskell.org/t/3666">Discourse topic</a>
</div>
<div class="pure-u-1-4">
</div>
</div>
<div><div class="license">
<p>
<span class="inline-centered">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">
<img alt="Creative Commons License" style="border-width:0" src="//i.creativecommons.org/l/by-sa/4.0/80x15.png" /></a>
</span>
<span class="inline-centered">
Post licensed under a
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.
</span>
</p>
</div>
</div>
]]></description>
<pubDate>2021-11-11T23:50:00-03:00</pubDate>
<guid>https://duplode.github.io/posts/divisible-and-the-monoidal-quartet.html</guid>
<dc:creator>Daniel Mlot</dc:creator>
</item>
<item>
<title>Idempotent Applicatives, Parametricity, and a Puzzle</title>
<link>https://duplode.github.io/posts/idempotent-applicatives-parametricity-and-a-puzzle.html</link>
<description><![CDATA[
<p>Some applicative functors are idempotent, in the sense that repeating an effect is the same as having it just once. An example and a counterexample are <code>Maybe</code> and <code>IO</code>, respectively (contrast <code>Just 3 *> Just 3</code> with <code>print 3 *> print 3</code>). More precisely, idempotency means that <code>f <$> u <*> u = (\x -> f x x) <$> u</code>. Given the informal description I began with, though, one might wonder whether the simpler property <code>u *> u = u</code>, which seems to capture the intuition about repeated effects, is equivalent to the usual idempotency property. In this post, I will tell how I went about exploring this conjecture, as well as a few things I learnt about parametricity along the way.</p>
<div>
</div>
<!--more-->
<p>Before I begin, a few remarks about this notion of idempotency. The earliest mention of it that I know of is in <em>Combining Monads</em>, a paper by King and Wadler <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>. There, idempotent monads are presented alongside the most widely known concept of commutative monads (<code>f <$> u <*> v = flip f <$> v <*> u</code>). Both properties generalise straightforwardly to applicative functors, which has the neat side-effect of allowing myself to skirt the ambiguity of the phrase “idempotent monad” (in category theory, that usually means a monad that, in Haskell parlance, has a <code>join</code> that is an isomorphism – a meaning that mostly doesn’t show up in Haskell). Lastly, I knew of the conjecture about idempotency amounting to <code>u *> u = u</code> through a Stack Overflow comment by David Feuer, and so I thank him for inspiring this post.</p>
<h2 id="prolegomena">Prolegomena</h2>
<p>Given we are looking into a general claim about applicatives, our first port of call are the applicative laws. Since the laws written in terms of <code>(<*>)</code> can be rather clunky to wield, I will switch to <a href="http://blog.ezyang.com/2012/08/applicative-functors">the monoidal presentation of <code>Applicative</code></a>:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- fzip and unit correspond to (<*>) and pure, respectively.</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="ot">fzip ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> (f a, f b) <span class="ot">-></span> f (a, b)</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>fzip (u, v) <span class="ot">=</span> (,) <span class="op"><$></span> u <span class="op"><*></span> v</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true" tabindex="-1"></a><span class="ot">unit ::</span> <span class="dt">Applicative</span> f <span class="ot">=></span> f ()</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true" tabindex="-1"></a>unit <span class="ot">=</span> <span class="fu">pure</span> ()</span></code></pre></div>
<p>Note I am using an uncurried version of <code>fzip</code>, as I feel it makes what follows slightly easier to explain. I will also introduce a couple teensy little combinators so that the required tuple shuffling becomes easier on the eye:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="ot">app ::</span> (a <span class="ot">-></span> b, a) <span class="ot">-></span> b</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>app (f, x) <span class="ot">=</span> f x</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a><span class="ot">dup ::</span> a <span class="ot">-></span> (a, a)</span>
<span id="cb2-5"><a href="#cb2-5" aria-hidden="true" tabindex="-1"></a>dup x <span class="ot">=</span> (x, x)</span>
<span id="cb2-6"><a href="#cb2-6" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-7"><a href="#cb2-7" aria-hidden="true" tabindex="-1"></a><span class="co">{-</span></span>
<span id="cb2-8"><a href="#cb2-8" aria-hidden="true" tabindex="-1"></a><span class="co">I will also use the Bifunctor methods for pairs, which amount to:</span></span>
<span id="cb2-9"><a href="#cb2-9" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb2-10"><a href="#cb2-10" aria-hidden="true" tabindex="-1"></a><span class="co">bimap f g (x, y) = (f x, g y)</span></span>
<span id="cb2-11"><a href="#cb2-11" aria-hidden="true" tabindex="-1"></a><span class="co">first f = bimap f id</span></span>
<span id="cb2-12"><a href="#cb2-12" aria-hidden="true" tabindex="-1"></a><span class="co">second g = bimap id g</span></span>
<span id="cb2-13"><a href="#cb2-13" aria-hidden="true" tabindex="-1"></a><span class="co">-}</span></span>
<span id="cb2-14"><a href="#cb2-14" aria-hidden="true" tabindex="-1"></a><span class="co">--</span></span></code></pre></div>
<p>The converse definitions of <code>pure</code> and <code>(<*>)</code> in terms of <code>unit</code> and <code>fzip</code> would be:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a>u <span class="op"><*></span> v <span class="ot">=</span> app <span class="op"><$></span> fzip (u, v)</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="fu">pure</span> x <span class="ot">=</span> <span class="fu">const</span> x <span class="op"><$></span> unit</span></code></pre></div>
<p>Using that vocabulary, the applicative laws become:</p>
<div class="sourceCode" id="cb4"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- "~" here means "the same up to a relevant isomorphism"</span></span>
<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a>fzip (u, unit) <span class="op">~</span> u <span class="co">-- up to pairing with ()</span></span>
<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a>fzip (unit, u) <span class="op">~</span> u <span class="co">-- up to pairing with ()</span></span>
<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a>fzip (fzip (u, v), w) <span class="op">~</span> fzip (u, fzip (v, w)) <span class="co">-- up to reassociating pairs</span></span></code></pre></div>
<p>As for the idempotency property, it can be expressed as:</p>
<div class="sourceCode" id="cb5"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a>fzip (u, u) <span class="ot">=</span> dup <span class="op"><$></span> u <span class="co">-- fzip . dup = fmap dup</span></span></code></pre></div>
<p><code>(*>)</code> and its sibling <code>(<*)</code> become:</p>
<div class="sourceCode" id="cb6"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a>u <span class="op"><*</span> v <span class="ot">=</span> <span class="fu">fst</span> <span class="op"><$></span> fzip (u, v)</span>
<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a>u <span class="op">*></span> v <span class="ot">=</span> <span class="fu">snd</span> <span class="op"><$></span> fzip (u, v)</span></code></pre></div>
<p>(Proofs of the claims just above can be found at the appendix at the end of this post.)</p>
<p>Finally, the conjecture amounts to:</p>
<div class="sourceCode" id="cb7"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="fu">snd</span> <span class="op"><$></span> fzip (u, u) <span class="ot">=</span> u <span class="co">-- u *> u = u</span></span>
<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="co">-- Is equivalent to...</span></span>
<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a>fzip (u, u) <span class="ot">=</span> dup <span class="op"><$></span> u <span class="co">-- idempotency</span></span></code></pre></div>
<p>That <code>fzip (u, u) = dup <$> u</code> implies <code>snd <$> fzip (u, u)</code> is immediate, as <code>snd . dup = id</code>. Our goal, then, is getting <code>fzip (u, u) = dup <$> u</code> out of <code>snd <$> fzip (u, u) = u</code>.</p>
<h2 id="drawing-relations">Drawing relations</h2>
<p>How might we get from <code>snd <$> fzip (u, u) = u</code> to <code>fzip (u, u) = dup <$> u</code>? It appears we have to take a fact about the second components of the pairs in <code>fzip (u, u)</code> (note that mapping <code>snd</code> discards the first components) and squeeze something about the first components out of it (namely, that they are equal to the second components everywhere). At first glance, it doesn’t appear the applicative laws connect the components in any obviously exploitable way. The one glimmer of hope lies in how, in the associativity law…</p>
<div class="sourceCode" id="cb8"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a>fzip (fzip (u, v), w) <span class="op">~</span> fzip (u, fzip (v, w)) <span class="co">-- up to reassociating pairs</span></span></code></pre></div>
<p>… whatever values originally belonging to <code>v</code> must show up as second components of pairs on the left hand side, and as first components on the right hand side. While that, on its own, is too vague to be actionable, there is a seemingly innocuous observation we can make use of: <code>snd <$> fzip (u, u) = u</code> tells us we can turn <code>fzip (u, u)</code> into <code>u</code> using <code>fmap</code> (informally, we can say that they have the same shape), and that they can be <em>related</em> using <code>snd</code> while making use of a free theorem <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>. For our current purposes, that means we can borrow the types involved in the left side of the associativity law and use them to draw the following diagram…</p>
<pre><code> fzip
(F (a, b), F c) --------> F ((a, b), c)
| | | |
| | | |
snd| |id snd| |id
| | | |
v v v v
(F b, F c ) --------> F ( b, c)
fzip</code></pre>
<p>… such that we get the same result by following either path from the top left corner to the bottom right one. Omitting the occurrences of <code>id</code>, we can state that through this equation:</p>
<div class="sourceCode" id="cb10"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> (first <span class="fu">snd</span>) <span class="op">.</span> fzip <span class="ot">=</span> fzip <span class="op">.</span> first (<span class="fu">fmap</span> <span class="fu">snd</span>)</span></code></pre></div>
<p>In words, it doesn’t matter whether we use <code>snd</code> after or before using <code>fzip</code>. <code>fmap</code> and <code>first</code>, left implicit in the diagram, are used to lift <code>snd</code> across the applicative layer and the pairs, respectively. This is just one specific instance of the free theorem; instead of <code>snd</code> and <code>id</code>, we could have any functions – or, more generally, any relations <a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>– between the involved types. Free theorems tell us about relations being preserved; in this case, <code>snd</code> sets up a relation on the left side of the diagram, and <code>fzip</code> preserves it.</p>
<p>We can get back to our problem by slipping in suitable concrete values in the equation. For an arbitrary <code>u :: F A</code>, we have…</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a>first <span class="fu">snd</span> <span class="op"><$></span> fzip (fzip (u, u), u) <span class="ot">=</span> fzip (<span class="fu">snd</span> <span class="op"><$></span> fzip (u, u), u)</span></code></pre></div>
<p>… and, thanks to our <code>snd <$> fzip (u, u) = u</code> premise:</p>
<div class="sourceCode" id="cb12"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a>first <span class="fu">snd</span> <span class="op"><$></span> fzip (fzip (u, u), u) <span class="ot">=</span> fzip (u, u)</span></code></pre></div>
<p>Now, why should we restrict ourselves to the left side of the associativity law? We can get a very similar diagram to work with from the right side:</p>
<pre><code> fzip
(F a, F (b, c)) --------> F (a, (b, c))
| | | |
| | | |
id| |snd id| |snd
| | | |
v v v v
(F a, F c ) --------> F (a, c )
fzip</code></pre>
<p>Or, as an equation:</p>
<div class="sourceCode" id="cb14"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="fu">fmap</span> (second <span class="fu">snd</span>) <span class="op">.</span> fzip <span class="ot">=</span> fzip <span class="op">.</span> second (<span class="fu">fmap</span> <span class="fu">snd</span>)</span></code></pre></div>
<p>Proceeding just like before, we get:</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a>second <span class="fu">snd</span> <span class="op"><$></span> fzip (u, fzip (u, u)) <span class="ot">=</span> fzip (u, <span class="fu">snd</span> <span class="op"><$></span> fzip (u, u))</span>
<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a>second <span class="fu">snd</span> <span class="op"><$></span> fzip (u, fzip (u, u)) <span class="ot">=</span> fzip (u, u)</span></code></pre></div>
<p>Since <code>fzip (u, fzip (u, u)) ~ fzip (fzip (u, u), u)</code> (associativity), we can shuffle that into:</p>
<div class="sourceCode" id="cb16"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co">-- Both first fst and second snd get rid of the value in the middle.</span></span>
<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a>first <span class="fu">fst</span> <span class="op"><$></span> fzip (fzip (u, u), u) <span class="ot">=</span> fzip (u, u)</span></code></pre></div>
<p>The equations we squeezed out of the diagrams…</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a>first <span class="fu">snd</span> <span class="op"><$></span> fzip (fzip (u, u), u) <span class="ot">=</span> fzip (u, u)</span>
<span id="cb17-2"><a href="#cb17-2" aria-hidden="true" tabindex="-1"></a>first <span class="fu">fst</span> <span class="op"><$></span> fzip (fzip (u, u), u) <span class="ot">=</span> fzip (u, u)</span></code></pre></div>
<p>… can be combined into:</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a>fzip (fzip (u, u), u) <span class="ot">=</span> first dup <span class="op"><$></span> fzip (u, u)</span></code></pre></div>
<p>This kind of looks like idempotency, except for the extra occurrence of <code>u</code> tagging along for the ride. We might have a go at getting rid of it by sketching a diagram of a slightly different nature, which shows how the relations play out across the specific values that appear in the equation above:</p>
<pre><code> fzip
(u, u) :: (F a , F a) -----------> F ( a , a)
| | | |
| | | |
R| S| {dup}| {id}|
| | | |
| | fzip | |
(fzip (u, u), u) :: (F (a, a), F a) -----------> F ((a, a), a)</code></pre>
<p><code>dup</code> can be used to relate <code>fzip (u, u)</code> and <code>fzip (fzip (u, u), u)</code> on the right of the diagram. That this diagram involves specific values leads to a subtle yet crucial difference from the previous ones: the relation on the right side is not necessarily the function <code>dup</code>, but some relation that happens to agree with <code>dup</code> <em>for the specific values we happen to be using here</em> (that is what I have attempted to suggest by adding the curly brackets as ad hoc notation and dropping the arrow tips from the vertical connectors). This is important because, given how <code>fzip</code> preserves relations, we might be tempted to work backwards and identify <code>R</code> on the left side with <code>dup</code>, giving us a proof – <code>dup <$> u = fzip (u, u)</code> would be an immediate consequence. We can’t do that, though, as <code>R</code> only must agree with <code>dup</code> for those values which show up in a relevant way on the right side. More explicitly, consider some element <code>x :: a</code> of <code>u</code>. If <code>x</code> shows up as a first component anywhere in <code>fzip (u, u)</code>, then the corresponding element of <code>fzip (u, u)</code> must have its first and second components equal to each other (because <code>dup</code> agrees with <code>R</code> on <code>x</code>, and <code>R</code> in turn relates <code>u</code> and <code>fzip (u, u)</code>), and to <code>x</code> (since <code>snd <$> fzip (u, u) = u</code>). If that held for all elements of <code>u</code>, we would have <code>fzip (u, u) = dup <$> u</code>. However if <code>x</code> <em>doesn’t</em> show up as a first component in <code>fzip (u, u)</code>, there are no guarantees (as the right side offers no evidence on what <code>x</code> is related to through <code>R</code>), and so we don’t have grounds for the ultimate claim.</p>
<p>Close, but no cigar.</p>
<h2 id="something-twisted">Something twisted</h2>
<p>While those parametricity tricks gave us no proof, we did learn something interesting: the conjecture holds as long as all elements from <code>u</code> show up as first components in <code>fzip (u, u)</code>. That sounds like a decent lead for a counterexample, so let’s switch course and look for one instead. To begin with, here is an inoffensive length-two vector/homogeneous pair type:</p>
<div class="sourceCode" id="cb20"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="ot">{-# LANGUAGE DeriveFunctor #-}</span></span>
<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Good</span> a <span class="ot">=</span> <span class="dt">Good</span> a a</span>
<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Ord</span>, <span class="dt">Functor</span>)</span></code></pre></div>
<p>Here is its <code>Applicative</code> instance, specified in terms of the monoidal presentation:</p>
<div class="sourceCode" id="cb21"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a>unit <span class="ot">=</span> <span class="dt">Good</span> () ()</span>
<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Good</span> (x1, y1) (x2, y2)</span></code></pre></div>
<p><code>Good</code>, like any other applicative with a single shape, is idempotent – as there is just one shape, it can’t help but be preserved <a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a>. That means we need a second constructor:</p>
<div class="sourceCode" id="cb22"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Twisted</span> a <span class="ot">=</span> <span class="dt">Evil</span> a a <span class="op">|</span> <span class="dt">Good</span> a a</span>
<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Eq</span>, <span class="dt">Show</span>, <span class="dt">Ord</span>, <span class="dt">Functor</span>)</span></code></pre></div>
<p><code>unit</code> can remain the same…</p>
<div class="sourceCode" id="cb23"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a>unit <span class="ot">=</span> <span class="dt">Good</span> () ()</span></code></pre></div>
<p>… which means the <code>Good</code>-and-<code>Good</code> case <em>must</em> remain the same: the identity effect has to be idempotent <a href="#fn5" class="footnote-ref" id="fnref5" role="doc-noteref"><sup>5</sup></a>:</p>
<div class="sourceCode" id="cb24"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Good</span> (x1, y1) (x2, y2)</span>
<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> _</span>
<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> _</span>
<span id="cb24-4"><a href="#cb24-4" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> _</span></code></pre></div>
<p>The twist comes in the <code>Evil</code>-and-<code>Evil</code> case: we repeat our pick of a first element of the vector, and thus discard one of the first elements. (We can’t do the same with the second element, as we want <code>snd <$> fzip (u, u) = u</code> to hold.)</p>
<div class="sourceCode" id="cb25"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Good</span> (x1, y1) (x2, y2)</span>
<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> <span class="dt">Evil</span> (x1, y1) (x1, y2)</span>
<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> _</span>
<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> _</span></code></pre></div>
<p>The <code>Evil</code>-and-<code>Good</code> case is determined by the right identity law…</p>
<div class="sourceCode" id="cb26"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Good</span> (x1, y1) (x2, y2)</span>
<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> <span class="dt">Evil</span> (x1, y2) (x2, y2)</span>
<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Evil</span> (x1, y1) (x2, y2)</span>
<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> _</span></code></pre></div>
<p>… while associativity forces our hand in the <code>Good</code>-and-<code>Evil</code> case (consider what would happen in a <code>Good</code>-<code>Evil</code>-<code>Evil</code> chain <a href="#fn6" class="footnote-ref" id="fnref6" role="doc-noteref"><sup>6</sup></a>):</p>
<div class="sourceCode" id="cb27"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Good</span> (x1, y1) (x2, y2)</span>
<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> <span class="dt">Evil</span> (x1, y1) (x1, y2)</span>
<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Evil</span> x1 x2, <span class="dt">Good</span> y1 y2) <span class="ot">=</span> <span class="dt">Evil</span> (x1, y1) (x2, y2)</span>
<span id="cb27-4"><a href="#cb27-4" aria-hidden="true" tabindex="-1"></a>fzip (<span class="dt">Good</span> x1 x2, <span class="dt">Evil</span> y1 y2) <span class="ot">=</span> <span class="dt">Evil</span> (x1, y1) (x1, y2)</span></code></pre></div>
<p><code>Evil</code> spreads, leaving a trail of repeated picks of first elements to the left of its rightmost occurrence in an applicative chain.</p>
<p>Getting an actual <code>Applicative</code> instance from those definitions is easy: fill <code>unit</code> with something, and take away the commas from <code>fzip</code>:</p>
<div class="sourceCode" id="cb28"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="kw">instance</span> <span class="dt">Applicative</span> <span class="dt">Twisted</span> <span class="kw">where</span></span>
<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a> <span class="fu">pure</span> x <span class="ot">=</span> <span class="dt">Good</span> x x</span>
<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a></span>
<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="dt">Good</span> x1 x2 <span class="op"><*></span> <span class="dt">Good</span> y1 y2 <span class="ot">=</span> <span class="dt">Good</span> (x1 y1) (x2 y2)</span>
<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> <span class="dt">Evil</span> x1 x2 <span class="op"><*></span> <span class="dt">Evil</span> y1 y2 <span class="ot">=</span> <span class="dt">Evil</span> (x1 y1) (x1 y2)</span>
<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> <span class="dt">Evil</span> x1 x2 <span class="op"><*></span> <span class="dt">Good</span> y1 y2 <span class="ot">=</span> <span class="dt">Evil</span> (x1 y1) (x2 y2)</span>
<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a> <span class="dt">Good</span> x1 x2 <span class="op"><*></span> <span class="dt">Evil</span> y1 y2 <span class="ot">=</span> <span class="dt">Evil</span> (x1 y1) (x1 y2) </span></code></pre></div>
<p>And there it is:</p>
<div class="sourceCode" id="cb29"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="dt">GHCi</span><span class="op">></span> test <span class="ot">=</span> <span class="dt">Evil</span> <span class="dv">1</span> <span class="dv">2</span></span>
<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a><span class="dt">GHCi</span><span class="op">></span> test <span class="op">*></span> test</span>
<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="dt">Evil</span> <span class="dv">1</span> <span class="dv">2</span></span>
<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a><span class="dt">GHCi</span><span class="op">></span> dup <span class="op"><$></span> test</span>
<span id="cb29-5"><a href="#cb29-5" aria-hidden="true" tabindex="-1"></a><span class="dt">Evil</span> (<span class="dv">1</span>,<span class="dv">1</span>) (<span class="dv">2</span>,<span class="dv">2</span>)</span>
<span id="cb29-6"><a href="#cb29-6" aria-hidden="true" tabindex="-1"></a><span class="dt">GHCi</span><span class="op">></span> fzip (test, test)</span>
<span id="cb29-7"><a href="#cb29-7" aria-hidden="true" tabindex="-1"></a><span class="dt">Evil</span> (<span class="dv">1</span>,<span class="dv">1</span>) (<span class="dv">1</span>,<span class="dv">2</span>)</span>
<span id="cb29-8"><a href="#cb29-8" aria-hidden="true" tabindex="-1"></a><span class="dt">GHCi</span><span class="op">></span> (\x <span class="ot">-></span> x <span class="op">+</span> x) <span class="op"><$></span> test</span>
<span id="cb29-9"><a href="#cb29-9" aria-hidden="true" tabindex="-1"></a><span class="dt">Evil</span> <span class="dv">2</span> <span class="dv">4</span></span>
<span id="cb29-10"><a href="#cb29-10" aria-hidden="true" tabindex="-1"></a><span class="dt">GHCi</span><span class="op">></span> (<span class="op">+</span>) <span class="op"><$></span> test <span class="op"><*></span> test</span>