-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathatom.xml
More file actions
1825 lines (1670 loc) · 225 KB
/
atom.xml
File metadata and controls
1825 lines (1670 loc) · 225 KB
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"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title><![CDATA[Spire Language Development Blog]]></title>
<link href="http://spire-lang.org/atom.xml" rel="self"/>
<link href="http://spire-lang.org/"/>
<updated>2014-08-14T13:44:12-07:00</updated>
<id>http://spire-lang.org/</id>
<author>
<name><![CDATA[Larry Diehl]]></name>
</author>
<generator uri="http://octopress.org/">Octopress</generator>
<entry>
<title type="html"><![CDATA[Inductive-Recursive Descriptions]]></title>
<link href="http://spire-lang.org/blog/2014/08/04/inductive-recursive-descriptions/"/>
<updated>2014-08-04T19:52:32-07:00</updated>
<id>http://spire-lang.org/blog/2014/08/04/inductive-recursive-descriptions</id>
<content type="html"><![CDATA[<p>This post is about adapting descriptions, used to encode dependently typed
datatypes (including type families) originally in
<a href="http://gallium.inria.fr/~pdagand/papers/levitation.pdf">The Gentle Art of Levitation</a>,
to inductive-recursive types.</p>
<!-- more -->
<h2>Goals</h2>
<p>There have been many encodings of [indexed] inductive-recursive types,
but as I developed Spire I came to desire an encoding that satisfied all
of the following criteria:</p>
<ul>
<li><strong>Is universe-polymorphic.</strong> Although it’s not hard to add universe
levels, it is crucial for an actual language implementation. Nevertheless, most
papers (justifiably) abstain from cluttering their presentation with
universe levels.</li>
<li><strong>Passes Agda’s termination & positivity checkers.</strong>
Many alternative encodings of IR types, especially the ones that
are
<a href="https://personal.cis.strath.ac.uk/neil.ghani/papers/ghani-mscs11.pdf">directly inspired by algebraic semantics [Ghani & Hancock]</a>
suffer from being too general to pass Agda’s termination or positivity
checkers.</li>
<li><strong>Has description constructors that directly correspond to
constructor declaration arguments.</strong>
Implementing a high-level language that translates to a canonical
kernel language is very difficult if the kernel language is too
different from the high-level language. For this reason I have chosen
to make the description (<code>Desc</code>) datatype enforce structure that is as
similar to a higher-level constructor telescope declaration as
possible. From the descriptions literature, this means extending the
<a href="https://personal.cis.strath.ac.uk/conor.mcbride/pub/OAAO/Ornament.pdf">propositional encoding [McBride]</a>
rather than the (albeit more general)
<a href="http://gallium.inria.fr/~pdagand/stuffs/thesis-2011-phd/thesis.pdf">computational encoding [Dagand]</a>.
From the IR literature, this means staying away from the more semantic
encodings described by
<a href="https://personal.cis.strath.ac.uk/neil.ghani/papers/ghani-mscs11.pdf">Ghani & Hancock</a>,
as well as subtle differences from the original encoding by Dybjer and
Setzer encoding, as reviewed by
<a href="https://personal.cis.strath.ac.uk/conor.mcbride/pub/SmallIR/SmallIR.pdf">Malatesta et. al.</a>.</li>
<li><strong>Has an induction principle.</strong>
The induction principle for encoded datatypes is typically given in
the description literature, but this is not always the case in the IR
literature. I also wanted an induction principle in the style of the description literature.</li>
</ul>
<h2>Non-Indexed Inductive-Recursive Descriptions</h2>
<p>I’m going to start with descriptions for non-indexed IR types, and move to
indexed IR types in the subsequent section. Additionally, I will mainly
focus on the definition of descriptions, and encoding types with
descriptions. The harder part is defining the fixpoint for encoded types
and the corresponding induction principle, which I briefly gloss over
at the end of the post. Additionally, all the code presented in this
post is linked to in the conclusion.</p>
<p>A common use of IR is to
model a dependently typed language. Below is the definition of an
example language. The datatype definition (<code>Lang</code>) is mutually defined
with an interpretation function whose domain is <code>Set</code>. Because the
codomain is <code>Set</code> (rather than some small type like <code>ℕ</code>), this makes
it a <em>large</em> inductive-recursive definition.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="nf">mutual</span>
</span><span class='line'> <span class="kr">data</span> <span class="kt">Lang</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span>
</span><span class='line'> <span class="kt">Zero</span> <span class="kt">One</span> <span class="kt">Two</span> <span class="kt">:</span> <span class="kt">Lang</span>
</span><span class='line'> <span class="kt">Pair</span> <span class="kt">Fun</span> <span class="kt">Tree</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Lang</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="err">⟦</span> <span class="kt">A</span> <span class="err">⟧</span> <span class="err">→</span> <span class="kt">Lang</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Lang</span>
</span><span class='line'>
</span><span class='line'> <span class="err">⟦</span><span class="kr">_</span><span class="err">⟧</span> <span class="kt">:</span> <span class="kt">Lang</span> <span class="err">→</span> <span class="kt">Set</span>
</span><span class='line'> <span class="err">⟦</span> <span class="kt">Zero</span> <span class="err">⟧</span> <span class="ow">=</span> <span class="err">⊥</span>
</span><span class='line'> <span class="err">⟦</span> <span class="kt">One</span> <span class="err">⟧</span> <span class="ow">=</span> <span class="err">⊤</span>
</span><span class='line'> <span class="err">⟦</span> <span class="kt">Two</span> <span class="err">⟧</span> <span class="ow">=</span> <span class="kt">Bool</span>
</span><span class='line'> <span class="err">⟦</span> <span class="kt">Pair</span> <span class="kt">A</span> <span class="kt">B</span> <span class="err">⟧</span> <span class="ow">=</span> <span class="kt">Σ</span> <span class="err">⟦</span> <span class="kt">A</span> <span class="err">⟧</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="err">⟦</span> <span class="kt">B</span> <span class="n">a</span> <span class="err">⟧</span>
</span><span class='line'> <span class="err">⟦</span> <span class="kt">Fun</span> <span class="kt">A</span> <span class="kt">B</span> <span class="err">⟧</span> <span class="ow">=</span> <span class="p">(</span><span class="n">a</span> <span class="kt">:</span> <span class="err">⟦</span> <span class="kt">A</span> <span class="err">⟧</span><span class="p">)</span> <span class="err">→</span> <span class="err">⟦</span> <span class="kt">B</span> <span class="n">a</span> <span class="err">⟧</span>
</span><span class='line'> <span class="err">⟦</span> <span class="kt">Tree</span> <span class="kt">A</span> <span class="kt">B</span> <span class="err">⟧</span> <span class="ow">=</span> <span class="kt">W</span> <span class="err">⟦</span> <span class="kt">A</span> <span class="err">⟧</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="err">⟦</span> <span class="kt">B</span> <span class="n">a</span> <span class="err">⟧</span>
</span></code></pre></td></tr></table></div></figure>
<p>I will encode <code>Lang</code> using the following description datatype
(<code>Desc</code>). <code>Desc</code> is parameterized by a datatype <code>O</code>, which is the type
of the codomain of the IR interpretation function.
It is easiest to think of the constructors of <code>Desc</code> as the pieces
used to form the telescope of a constructor type declaration, such as
<code>Two</code> and <code>Pair</code> in <code>Lang</code>.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="kr">data</span> <span class="kt">Desc</span> <span class="p">{</span><span class="n">ℓ</span><span class="p">}</span> <span class="p">(</span><span class="kt">O</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="p">(</span><span class="n">lsuc</span> <span class="n">ℓ</span><span class="p">)</span> <span class="kr">where</span>
</span><span class='line'> <span class="kt">End</span> <span class="kt">:</span> <span class="p">(</span><span class="n">o</span> <span class="kt">:</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span>
</span><span class='line'> <span class="kt">Rec</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">O</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span>
</span><span class='line'> <span class="kt">Ref</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="p">(</span><span class="n">o</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span>
</span><span class='line'> <span class="kt">Arg</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">O</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>End</code> ends a constructor declaration, and specifies what the
mutually-defined IR interpretation function returns for the
constructor. <code>Rec</code> encodes a request for a recursive first-order
argument, and the remainder of the telescope may depend on the
interpretation function applied to this recursive argument.
<code>Ref</code> encodes a request for a recursive function argument. To remain
strictly positive, <code>Ref</code> asks for the type of the domain of the
function argument, and the remainder of the telescope may depend on a
function from a value of the domain of the function to the
interpretation function applied to the result of the recursive function
that <code>Ref</code> encodes.
<code>Arg</code> records an ordinary argument by requesting the type of the
argument, and the remainder of the telescope may depend on a value of
that type.</p>
<p>Below is the encoding of the the <code>Lang</code> datatype, and its
interpretation function, as a description.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="kr">data</span> <span class="kt">LangT</span> <span class="p">{</span><span class="n">ℓ</span><span class="p">}</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span> <span class="kr">where</span>
</span><span class='line'> <span class="kt">ZeroT</span> <span class="kt">OneT</span> <span class="kt">TwoT</span> <span class="kt">PairT</span> <span class="kt">FunT</span> <span class="kt">TreeT</span> <span class="kt">:</span> <span class="kt">LangT</span>
</span><span class='line'>
</span><span class='line'><span class="kt">LangD</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="p">(</span><span class="kt">Set</span> <span class="n">lzero</span><span class="p">)</span>
</span><span class='line'><span class="kt">LangD</span> <span class="ow">=</span> <span class="kt">Arg</span> <span class="kt">LangT</span> <span class="n">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="kt">ZeroT</span> <span class="err">→</span> <span class="kt">End</span> <span class="err">⊥</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">OneT</span> <span class="err">→</span> <span class="kt">End</span> <span class="err">⊤</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">TwoT</span> <span class="err">→</span> <span class="kt">End</span> <span class="kt">Bool</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">PairT</span> <span class="err">→</span> <span class="kt">Rec</span> <span class="n">λ</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Ref</span> <span class="p">(</span><span class="kt">Lift</span> <span class="kt">A</span><span class="p">)</span> <span class="n">λ</span> <span class="kt">B</span> <span class="err">→</span> <span class="kt">End</span> <span class="p">(</span><span class="kt">Σ</span> <span class="kt">A</span> <span class="p">(</span><span class="kt">B</span> <span class="err">∘</span> <span class="n">lift</span><span class="p">))</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">FunT</span> <span class="err">→</span> <span class="kt">Rec</span> <span class="n">λ</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Ref</span> <span class="p">(</span><span class="kt">Lift</span> <span class="kt">A</span><span class="p">)</span> <span class="n">λ</span> <span class="kt">B</span> <span class="err">→</span> <span class="kt">End</span> <span class="p">((</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">B</span> <span class="p">(</span><span class="n">lift</span> <span class="n">a</span><span class="p">))</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">TreeT</span> <span class="err">→</span> <span class="kt">Rec</span> <span class="n">λ</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Ref</span> <span class="p">(</span><span class="kt">Lift</span> <span class="kt">A</span><span class="p">)</span> <span class="n">λ</span> <span class="kt">B</span> <span class="err">→</span> <span class="kt">End</span> <span class="p">(</span><span class="kt">W</span> <span class="kt">A</span> <span class="p">(</span><span class="kt">B</span> <span class="err">∘</span> <span class="n">lift</span><span class="p">))</span>
</span><span class='line'> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<p>The <code>Two</code> constructor takes no arguments, and its interpretation
function returns the <code>Bool</code> type, and the <code>Zero</code> and <code>One</code> cases are
similar.
The <code>Pair</code> constructor first takes a
recursive argument, so the rest of the telescope can depend on its
interpretation. Then, it takes a recursive function argument whose
domain is the interpretation of the first argument. Once again, the
remainder of the telescope may depend on the the <em>function</em> from the
requested domain to the interpretation function result. Finally, the
constructor declaration ends by saying that the interpretation of
<code>Pair</code> as a whole is the sigma type (<code>Σ</code>) that we expect. The <code>Fun</code>
and <code>Tree</code> constructors are encoded in the same way that <code>Pair</code> is.
Also, I sprinkle <code>Lift</code> and <code>lift</code> in the right places to make the
universe levels work out.</p>
<p>Another standard example of a <em>small</em> inductive-recursive definition
is an interpreter of an arithmetic language, as presented by
<a href="https://personal.cis.strath.ac.uk/conor.mcbride/pub/SmallIR/SmallIR.pdf">Malatesta et. al.</a>.
The idea is to express mathematical sums and products, where the
domain of the sum or product specifies the bound on the iteration. See
the paper for an in depth explanation, but below is the high-level
code for the <code>Arith</code> type.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="nf">sum</span> <span class="kt">:</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">f</span> <span class="kt">:</span> <span class="kt">Fin</span> <span class="n">n</span> <span class="err">→</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="err">→</span> <span class="kt">ℕ</span>
</span><span class='line'><span class="nf">sum</span> <span class="n">zero</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">zero</span>
</span><span class='line'><span class="nf">sum</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">f</span> <span class="n">zero</span> <span class="o">+</span> <span class="n">sum</span> <span class="n">n</span> <span class="p">(</span><span class="n">f</span> <span class="err">∘</span> <span class="n">suc</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">prod</span> <span class="kt">:</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">f</span> <span class="kt">:</span> <span class="kt">Fin</span> <span class="n">n</span> <span class="err">→</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="err">→</span> <span class="kt">ℕ</span>
</span><span class='line'><span class="nf">prod</span> <span class="n">zero</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">suc</span> <span class="n">zero</span>
</span><span class='line'><span class="nf">prod</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">f</span> <span class="n">zero</span> <span class="o">*</span> <span class="n">prod</span> <span class="n">n</span> <span class="p">(</span><span class="n">f</span> <span class="err">∘</span> <span class="n">suc</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">mutual</span>
</span><span class='line'> <span class="kr">data</span> <span class="kt">Arith</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span>
</span><span class='line'> <span class="kt">Num</span> <span class="kt">:</span> <span class="kt">ℕ</span> <span class="err">→</span> <span class="kt">Arith</span>
</span><span class='line'> <span class="kt">Sum</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Arith</span><span class="p">)</span> <span class="p">(</span><span class="n">f</span> <span class="kt">:</span> <span class="kt">Fin</span> <span class="p">(</span><span class="n">eval</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Arith</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Arith</span>
</span><span class='line'> <span class="kt">Prod</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Arith</span><span class="p">)</span> <span class="p">(</span><span class="n">f</span> <span class="kt">:</span> <span class="kt">Fin</span> <span class="p">(</span><span class="n">eval</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Arith</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Arith</span>
</span><span class='line'>
</span><span class='line'> <span class="n">eval</span> <span class="kt">:</span> <span class="kt">Arith</span> <span class="err">→</span> <span class="kt">ℕ</span>
</span><span class='line'> <span class="n">eval</span> <span class="p">(</span><span class="kt">Num</span> <span class="n">n</span><span class="p">)</span> <span class="ow">=</span> <span class="n">n</span>
</span><span class='line'> <span class="n">eval</span> <span class="p">(</span><span class="kt">Sum</span> <span class="kt">A</span> <span class="n">f</span><span class="p">)</span> <span class="ow">=</span> <span class="n">sum</span> <span class="p">(</span><span class="n">eval</span> <span class="kt">A</span><span class="p">)</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="n">sum</span> <span class="p">(</span><span class="n">toℕ</span> <span class="n">a</span><span class="p">)</span> <span class="n">λ</span> <span class="n">b</span> <span class="err">→</span> <span class="n">eval</span> <span class="p">(</span><span class="n">f</span> <span class="p">(</span><span class="n">inject</span> <span class="n">b</span><span class="p">))</span>
</span><span class='line'> <span class="n">eval</span> <span class="p">(</span><span class="kt">Prod</span> <span class="kt">A</span> <span class="n">f</span><span class="p">)</span> <span class="ow">=</span> <span class="n">prod</span> <span class="p">(</span><span class="n">eval</span> <span class="kt">A</span><span class="p">)</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="n">sum</span> <span class="p">(</span><span class="n">toℕ</span> <span class="n">a</span><span class="p">)</span> <span class="n">λ</span> <span class="n">b</span> <span class="err">→</span> <span class="n">eval</span> <span class="p">(</span><span class="n">f</span> <span class="p">(</span><span class="n">inject</span> <span class="n">b</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="nf">sum</span><span class="o">-</span><span class="n">lt</span><span class="o">-</span><span class="mi">5</span> <span class="kt">:</span> <span class="kt">Arith</span>
</span><span class='line'><span class="nf">sum</span><span class="o">-</span><span class="n">lt</span><span class="o">-</span><span class="mi">5</span> <span class="ow">=</span> <span class="kt">Sum</span> <span class="p">(</span><span class="kt">Num</span> <span class="mi">5</span><span class="p">)</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">Num</span> <span class="p">(</span><span class="n">toℕ</span> <span class="n">a</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">test</span><span class="o">-</span><span class="n">eval</span> <span class="kt">:</span> <span class="n">eval</span> <span class="n">sum</span><span class="o">-</span><span class="n">lt</span><span class="o">-</span><span class="mi">5</span> <span class="err">≡</span> <span class="mi">10</span>
</span><span class='line'><span class="nf">test</span><span class="o">-</span><span class="n">eval</span> <span class="ow">=</span> <span class="n">refl</span>
</span></code></pre></td></tr></table></div></figure>
<p>Note the that it is a <em>small</em> IR type because the codomain of the
interpretation function is a small type (<code>ℕ</code>). Below is the Desc encoding,
which is very similar to what Malatesta et. al. give.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="nf">sum</span> <span class="kt">:</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">f</span> <span class="kt">:</span> <span class="kt">Fin</span> <span class="n">n</span> <span class="err">→</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="err">→</span> <span class="kt">ℕ</span>
</span><span class='line'><span class="nf">sum</span> <span class="n">zero</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">zero</span>
</span><span class='line'><span class="nf">sum</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">f</span> <span class="n">zero</span> <span class="o">+</span> <span class="n">sum</span> <span class="n">n</span> <span class="p">(</span><span class="n">f</span> <span class="err">∘</span> <span class="n">suc</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">prod</span> <span class="kt">:</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">f</span> <span class="kt">:</span> <span class="kt">Fin</span> <span class="n">n</span> <span class="err">→</span> <span class="kt">ℕ</span><span class="p">)</span> <span class="err">→</span> <span class="kt">ℕ</span>
</span><span class='line'><span class="nf">prod</span> <span class="n">zero</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">suc</span> <span class="n">zero</span>
</span><span class='line'><span class="nf">prod</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="n">f</span> <span class="ow">=</span> <span class="n">f</span> <span class="n">zero</span> <span class="o">*</span> <span class="n">prod</span> <span class="n">n</span> <span class="p">(</span><span class="n">f</span> <span class="err">∘</span> <span class="n">suc</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="kr">data</span> <span class="kt">ArithT</span> <span class="p">{</span><span class="n">ℓ</span><span class="p">}</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span> <span class="kr">where</span>
</span><span class='line'> <span class="kt">NumT</span> <span class="kt">SumT</span> <span class="kt">ProdT</span> <span class="kt">:</span> <span class="kt">ArithT</span>
</span><span class='line'>
</span><span class='line'><span class="kt">ArithD</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">ℕ</span>
</span><span class='line'><span class="kt">ArithD</span> <span class="ow">=</span> <span class="kt">Arg</span> <span class="kt">ArithT</span> <span class="n">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="kt">NumT</span> <span class="err">→</span> <span class="kt">Arg</span> <span class="kt">ℕ</span> <span class="n">λ</span> <span class="n">n</span> <span class="err">→</span> <span class="kt">End</span> <span class="n">n</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">SumT</span> <span class="err">→</span> <span class="kt">Rec</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">Ref</span> <span class="p">(</span><span class="kt">Fin</span> <span class="n">a</span><span class="p">)</span> <span class="n">λ</span> <span class="n">f</span> <span class="err">→</span> <span class="kt">End</span> <span class="p">(</span><span class="n">sum</span> <span class="n">a</span> <span class="n">f</span><span class="p">)</span>
</span><span class='line'> <span class="p">;</span> <span class="kt">ProdT</span> <span class="err">→</span> <span class="kt">Rec</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">Ref</span> <span class="p">(</span><span class="kt">Fin</span> <span class="n">a</span><span class="p">)</span> <span class="n">λ</span> <span class="n">f</span> <span class="err">→</span> <span class="kt">End</span> <span class="p">(</span><span class="n">prod</span> <span class="n">a</span> <span class="n">f</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>
<h2>Indexed Inductive-Recursive Descriptions</h2>
<p>Both the <code>Lang</code> and <code>Arith</code> types had interpretations whose codomain
was some constant value (<code>Set</code> and <code>ℕ</code> respectively). More generally,
an inductive-recursive type may be indexed, and the codomain of the
interpretation function may also be a type family. For example, you can
imagine a type like <code>Type : ℕ → Set</code> where the index type is <code>I = ℕ</code>,
and an interpretation function <code>eval : (n : ℕ) → Type n → Fin n</code> where
the interpretation type is <code>O = Fin</code>.</p>
<p>Below is the description type <code>Desc</code> modified to be able to encode
indexed inductive-recursive definitions. It now takes an
index type (<code>(I : Set ℓ)</code>) as an additional parameter to the
(now dependent) interpretation type (<code>(O : I → Set ℓ)</code>).</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="kr">data</span> <span class="kt">Desc</span> <span class="p">{</span><span class="n">ℓ</span><span class="p">}</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="p">(</span><span class="kt">O</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="p">(</span><span class="n">lsuc</span> <span class="n">ℓ</span><span class="p">)</span> <span class="kr">where</span>
</span><span class='line'> <span class="kt">End</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="n">o</span> <span class="kt">:</span> <span class="kt">O</span> <span class="n">i</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span>
</span><span class='line'> <span class="kt">Rec</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">O</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span>
</span><span class='line'> <span class="kt">Ref</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="p">(</span><span class="n">o</span> <span class="kt">:</span> <span class="p">(</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">O</span> <span class="p">(</span><span class="n">i</span> <span class="n">a</span><span class="p">))</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span>
</span><span class='line'> <span class="kt">Arg</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span>
</span></code></pre></td></tr></table></div></figure>
<p>The new <code>Desc</code> is a mixture of the old one (which is a slightly modified
Dybjer-Setzer IR type) , and the indexed description by
<a href="https://personal.cis.strath.ac.uk/conor.mcbride/pub/OAAO/Ornament.pdf">McBride</a>.
Recall that descriptions encode constructor argument telescopes. At
the end of a telescope (<code>End</code>), we must now specify what index the type is
at, as well as the (dependent) value that the interpretation function
returns for the constructor being defined. A recursive (<code>Rec</code>)
argument requires the index at for the requested recursive type, and
the remainder of the telescope of arguments may use the (dependent)
result of the interpretation function. A recursive function argument
(<code>Ref</code>) requires the type of the domain of the recursive argument, an
index value (<code>I</code>) assuming the requested argument (<code>A</code>), and the rest
of the constructor arguments telescope may depend on a <em>function</em> from
the requested argument to the (dependent) interpretation function
call. Finally, requesting an ordinary argument (<code>Arg</code>) is just as
before.</p>
<p>So far we have only looked at descriptions, but they are relatively
useless and easy to get wrong if you haven’t defined the corresponding
fixpoint type (which interprets a description of a type as an actual
type). First let’s look at <code>El</code>, which interprets a description as a
functor between indexed families of sets.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="kt">El</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">ℓ</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="p">(</span><span class="kt">X</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="p">(</span><span class="kt">Y</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="err">→</span> <span class="kt">X</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">O</span> <span class="n">i</span><span class="p">)</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span>
</span><span class='line'><span class="kt">El</span> <span class="p">(</span><span class="kt">End</span> <span class="n">j</span> <span class="n">o</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span> <span class="ow">=</span> <span class="n">j</span> <span class="err">≡</span> <span class="n">i</span>
</span><span class='line'><span class="kt">El</span> <span class="p">(</span><span class="kt">Rec</span> <span class="n">j</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span> <span class="ow">=</span> <span class="kt">Σ</span> <span class="p">(</span><span class="kt">X</span> <span class="n">j</span><span class="p">)</span> <span class="n">λ</span> <span class="n">x</span> <span class="err">→</span> <span class="kt">El</span> <span class="p">(</span><span class="kt">B</span> <span class="p">(</span><span class="kt">Y</span> <span class="n">x</span><span class="p">))</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span>
</span><span class='line'><span class="kt">El</span> <span class="p">(</span><span class="kt">Ref</span> <span class="kt">A</span> <span class="n">j</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span> <span class="ow">=</span> <span class="kt">Σ</span> <span class="p">((</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">X</span> <span class="p">(</span><span class="n">j</span> <span class="n">a</span><span class="p">))</span> <span class="n">λ</span> <span class="n">f</span> <span class="err">→</span> <span class="kt">El</span> <span class="p">(</span><span class="kt">B</span> <span class="p">(</span><span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">Y</span> <span class="p">(</span><span class="n">f</span> <span class="n">a</span><span class="p">)))</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span>
</span><span class='line'><span class="kt">El</span> <span class="p">(</span><span class="kt">Arg</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span> <span class="ow">=</span> <span class="kt">Σ</span> <span class="kt">A</span> <span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">El</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span>
</span></code></pre></td></tr></table></div></figure>
<p><code>El</code> gets an additional argument (<code>Y</code>), representing the interpretation
function of the described datatype. To define <code>El</code>, we must use <code>Y</code> wherever
we need to get the description from the codomain (<code>B</code>) of a recursive
first-order (<code>Rec</code>) or higher-order (<code>Ref</code>) argument.</p>
<p>More interestingly, we can now define the fixpoint datatype <code>μ</code>.</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="nf">mutual</span>
</span><span class='line'> <span class="kr">data</span> <span class="n">μ</span> <span class="p">{</span><span class="n">ℓ</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">init</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">D</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">D</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">D</span><span class="p">)</span> <span class="n">i</span> <span class="err">→</span> <span class="n">μ</span> <span class="kt">D</span> <span class="n">i</span>
</span><span class='line'>
</span><span class='line'> <span class="n">foldO</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">ℓ</span><span class="p">}</span> <span class="p">{</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">}</span> <span class="p">{</span><span class="kt">O</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">}</span> <span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="n">μ</span> <span class="kt">D</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">O</span> <span class="n">i</span>
</span><span class='line'> <span class="n">foldO</span> <span class="kt">D</span> <span class="p">(</span><span class="n">init</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">foldsO</span> <span class="kt">D</span> <span class="kt">D</span> <span class="n">xs</span>
</span><span class='line'>
</span><span class='line'> <span class="n">foldsO</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">ℓ</span><span class="p">}</span> <span class="p">{</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">}</span> <span class="p">{</span><span class="kt">O</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">}</span> <span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">E</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="err">→</span> <span class="kt">El</span> <span class="kt">D</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">E</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span><span class="p">)</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">O</span> <span class="n">i</span>
</span><span class='line'> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">End</span> <span class="n">j</span> <span class="n">o</span><span class="p">)</span> <span class="kt">E</span> <span class="n">refl</span> <span class="ow">=</span> <span class="n">o</span>
</span><span class='line'> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">Rec</span> <span class="n">j</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">E</span> <span class="p">(</span><span class="n">x</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">B</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span> <span class="n">x</span> <span class="p">))</span> <span class="kt">E</span> <span class="n">xs</span>
</span><span class='line'> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">Ref</span> <span class="kt">A</span> <span class="n">j</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">E</span> <span class="p">(</span><span class="n">f</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">B</span> <span class="p">(</span><span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="n">foldO</span> <span class="kt">E</span> <span class="p">(</span><span class="n">f</span> <span class="n">a</span><span class="p">)))</span> <span class="kt">E</span> <span class="n">xs</span>
</span><span class='line'> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">Arg</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">E</span> <span class="p">(</span><span class="n">a</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">foldsO</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">E</span> <span class="n">xs</span>
</span></code></pre></td></tr></table></div></figure>
<p>I tried to define this a couple of years ago but stuck for some
reason. I tried once again a couple of days ago and arrived at this
definition. In the IR literature <code>El</code> is
<a href="https://personal.cis.strath.ac.uk/neil.ghani/papers/ghani-mscs11.pdf">sometimes referred to</a> as
<code>⟦_⟧₀</code>, and a more general version of <code>foldsO</code> is referred to as
<code>⟦_⟧₁</code>. However, to get <code>foldO</code> to pass Agda’s termination check we must inline a
mutually defined specialized version of <code>⟦_⟧₁</code>, namely <code>foldsO</code>. This
is basically the same trick used to get the elimination principle
<code>ind</code> to terminate by inlining <code>hyps</code>. I remember trying to reuse this
termination technique a couple
of years ago and failing, but anyhow there it is.</p>
<p>Finally, for the sake of completeness below is the adapted definition
of <code>Hyps</code> (a collection of inductive hypotheses), <code>ind</code> (the primitive
induction principle for described types), and <code>hyps</code> (a specialized
mapping function to collect inductive hypotheses).</p>
<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
</pre></td><td class='code'><pre><code class='Haskell'><span class='line'><span class="kt">Hyps</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">ℓ</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span> <span class="p">(</span><span class="kt">X</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="p">(</span><span class="kt">Y</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="err">→</span> <span class="kt">X</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">O</span> <span class="n">i</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="kt">P</span> <span class="kt">:</span> <span class="p">{</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">}</span> <span class="err">→</span> <span class="kt">X</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">D</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="n">i</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span>
</span><span class='line'><span class="kt">Hyps</span> <span class="p">(</span><span class="kt">End</span> <span class="n">j</span> <span class="n">o</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">q</span> <span class="ow">=</span> <span class="kt">Lift</span> <span class="err">⊤</span>
</span><span class='line'><span class="kt">Hyps</span> <span class="p">(</span><span class="kt">Rec</span> <span class="n">j</span> <span class="kt">D</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="p">(</span><span class="n">x</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="kt">Σ</span> <span class="p">(</span><span class="kt">P</span> <span class="n">x</span><span class="p">)</span> <span class="p">(</span><span class="n">λ</span> <span class="kr">_</span> <span class="err">→</span> <span class="kt">Hyps</span> <span class="p">(</span><span class="kt">D</span> <span class="p">(</span><span class="kt">Y</span> <span class="n">x</span><span class="p">))</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">xs</span><span class="p">)</span>
</span><span class='line'><span class="kt">Hyps</span> <span class="p">(</span><span class="kt">Ref</span> <span class="kt">A</span> <span class="n">j</span> <span class="kt">D</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="p">(</span><span class="n">f</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="kt">Σ</span> <span class="p">((</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">P</span> <span class="p">(</span><span class="n">f</span> <span class="n">a</span><span class="p">))</span> <span class="p">(</span><span class="n">λ</span> <span class="kr">_</span> <span class="err">→</span> <span class="kt">Hyps</span> <span class="p">(</span><span class="kt">D</span> <span class="p">(</span><span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">Y</span> <span class="p">(</span><span class="n">f</span> <span class="n">a</span><span class="p">)))</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">xs</span><span class="p">)</span>
</span><span class='line'><span class="kt">Hyps</span> <span class="p">(</span><span class="kt">Arg</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="p">(</span><span class="n">a</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="kt">Hyps</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">X</span> <span class="kt">Y</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">xs</span>
</span><span class='line'>
</span><span class='line'><span class="c1">----------------------------------------------------------------------</span>
</span><span class='line'>
</span><span class='line'><span class="nf">ind</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">ℓ</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="kt">P</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="err">→</span> <span class="n">μ</span> <span class="kt">D</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="n">α</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">D</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">D</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">D</span><span class="p">)</span> <span class="n">i</span><span class="p">)</span> <span class="p">(</span><span class="n">ihs</span> <span class="kt">:</span> <span class="kt">Hyps</span> <span class="kt">D</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">D</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">D</span><span class="p">)</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">xs</span><span class="p">)</span> <span class="err">→</span> <span class="kt">P</span> <span class="p">(</span><span class="n">init</span> <span class="n">xs</span><span class="p">))</span>
</span><span class='line'> <span class="p">{</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">}</span>
</span><span class='line'> <span class="p">(</span><span class="n">x</span> <span class="kt">:</span> <span class="n">μ</span> <span class="kt">D</span> <span class="n">i</span><span class="p">)</span>
</span><span class='line'> <span class="err">→</span> <span class="kt">P</span> <span class="n">x</span>
</span><span class='line'>
</span><span class='line'><span class="nf">hyps</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">ℓ</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">}</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">E</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span> <span class="kt">O</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="kt">P</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="err">→</span> <span class="n">μ</span> <span class="kt">E</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">Set</span> <span class="n">ℓ</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="n">α</span> <span class="kt">:</span> <span class="err">∀</span><span class="p">{</span><span class="n">i</span><span class="p">}</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">E</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">E</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span><span class="p">)</span> <span class="n">i</span><span class="p">)</span> <span class="p">(</span><span class="n">ihs</span> <span class="kt">:</span> <span class="kt">Hyps</span> <span class="kt">E</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">E</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span><span class="p">)</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">xs</span><span class="p">)</span> <span class="err">→</span> <span class="kt">P</span> <span class="p">(</span><span class="n">init</span> <span class="n">xs</span><span class="p">))</span>
</span><span class='line'> <span class="p">{</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">}</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">D</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">E</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span><span class="p">)</span> <span class="n">i</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Hyps</span> <span class="kt">D</span> <span class="p">(</span><span class="n">μ</span> <span class="kt">E</span><span class="p">)</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span><span class="p">)</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">xs</span>
</span><span class='line'>
</span><span class='line'><span class="nf">ind</span> <span class="kt">D</span> <span class="kt">P</span> <span class="n">α</span> <span class="p">(</span><span class="n">init</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">α</span> <span class="n">xs</span> <span class="p">(</span><span class="n">hyps</span> <span class="kt">D</span> <span class="kt">D</span> <span class="kt">P</span> <span class="n">α</span> <span class="n">xs</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">hyps</span> <span class="p">(</span><span class="kt">End</span> <span class="n">i</span> <span class="n">o</span><span class="p">)</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="n">q</span> <span class="ow">=</span> <span class="n">lift</span> <span class="n">tt</span>
</span><span class='line'><span class="nf">hyps</span> <span class="p">(</span><span class="kt">Rec</span> <span class="n">i</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="p">(</span><span class="n">x</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">ind</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="n">x</span> <span class="p">,</span> <span class="n">hyps</span> <span class="p">(</span><span class="kt">B</span> <span class="p">(</span><span class="n">foldO</span> <span class="kt">E</span> <span class="n">x</span><span class="p">))</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="n">xs</span>
</span><span class='line'><span class="nf">hyps</span> <span class="p">(</span><span class="kt">Ref</span> <span class="kt">A</span> <span class="n">i</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="p">(</span><span class="n">f</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="p">(</span><span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="n">ind</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="p">(</span><span class="n">f</span> <span class="n">a</span><span class="p">))</span> <span class="p">,</span> <span class="n">hyps</span> <span class="p">(</span><span class="kt">B</span> <span class="p">(</span><span class="n">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="n">foldO</span> <span class="kt">E</span> <span class="p">(</span><span class="n">f</span> <span class="n">a</span><span class="p">)))</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="n">xs</span>
</span><span class='line'><span class="nf">hyps</span> <span class="p">(</span><span class="kt">Arg</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="p">(</span><span class="n">a</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="ow">=</span> <span class="n">hyps</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">E</span> <span class="kt">P</span> <span class="n">α</span> <span class="n">xs</span>
</span></code></pre></td></tr></table></div></figure>
<h2>Conclusion</h2>
<p>Well there it is, indexed inductive-recursive descriptions that
satisfy all of my goals stated at the beginning of the post! The
beginning of the post was background on non-indexed IR encoding.
However, the useful bit of the code to reuse is in the previous
section, which includes the universe-polymorphic, indexed,
inductive-recursive, constructor-esque descriptions, as well as their primitive
introduction and elimination rules.</p>
<p>The code used throughout the post is linked below:</p>
<ul>
<li><a href="https://github.com/spire/spire.github.io/blob/source/source/_code/2014-08-04-inductive-recursive-descriptions/IR.agda">Declared Non-Indexed IR</a></li>
<li><a href="https://github.com/spire/spire.github.io/blob/source/source/_code/2014-08-04-inductive-recursive-descriptions/DescIR.agda">Encoded Non-Indexed IR</a></li>
<li><a href="https://github.com/spire/spire.github.io/blob/source/source/_code/2014-08-04-inductive-recursive-descriptions/IDescIR.agda">Encoded Indexed IR</a></li>
</ul>
<p>If you want some homework, try inventing your own indexed
inductive-recursive type, and encode it both in Agda and as a
description. You can also borrow a type to encode from
<a href="http://www.cse.chalmers.se/~peterd/papers/Indexed_IR.pdf">Dybjer & Setzer’s paper on the topic</a>.</p>
]]></content>
</entry>
<entry>
<title type="html"><![CDATA[Modeling Elimination of Described Types]]></title>
<link href="http://spire-lang.org/blog/2014/01/15/modeling-elimination-of-described-types/"/>
<updated>2014-01-15T09:50:12-08:00</updated>
<id>http://spire-lang.org/blog/2014/01/15/modeling-elimination-of-described-types</id>
<content type="html"><![CDATA[<p>Before jumping straight into implementing datatypes via descriptions,
it is convient to be able model some of them in Agda (as done in
<a href="http://gallium.inria.fr/~pdagand/papers/levitation.pdf">The Gentle Art of Levitation</a>
by Chapman et. al.
and subsequent papers). Everything in the surface language, such as
datatype declarations and pattern matching, is elaborated to terms of
the core type theory. It is desirable to have the ingredients of the
core type theory be as similar to their higher level counterparts as
possible, otherwise work on the canonical terms (such as embedding
back upwards, generic programming on core terms, and compilation of
core terms) becomes complex.</p>
<!-- more -->
<p>My desired features for a bare bones version 1 of Spire include:</p>
<ul>
<li>implicit arguments</li>
<li>elaboration of datatype declarations to descriptions</li>
<li>elaboration of pattern matching syntax to eliminators</li>
<li>later superceded by elaboration to the “by” gadget from
<a href="http://strictlypositive.org/view.ps.gz">The view from the left</a> by McBride</li>
<li>sugar for performing generic programming over descriptions</li>
<li>formal metatheory for the canonical type theory</li>
<li>universe levels</li>
</ul>
<p>Rather than implementing this all at once, certain features are
gradually being added. However, it is still a good idea to have future
features in mind when implementing something, and the Agda model helps
with that. The process goes like this:</p>
<ol>
<li>Write down the high-level notation that Agda supports natively (or
in a comment, for features that Agda does not support)</li>
<li>Manually perform the elaboration procedures on paper</li>
<li>Typecheck and study the resulting core type theory terms</li>
</ol>
<p>Elaboration of a high level term can involve many steps that
are individually easy to follow, but produce a complex final term, and
it is worth considering alternative core type theory constructs to
produce simpler final terms. These sorts of before-and-after pictures,
and most concepts in this post, can be found in
<a href="http://gallium.inria.fr/~pdagand/stuffs/thesis-2011-phd/thesis.pdf">Pierre Dagand’s thesis</a>.</p>
<h2>Note</h2>
<p>All of the code from this post can be
<a href="https://github.com/spire/spire/tree/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples">found in Spire</a>.
Additionally, each code snippet contains a link to the specific file
in the <strong>top right corner</strong>.</p>
<h2>Pattern Matching</h2>
<p>When first implementing the <code>Desc</code>ription technology, it will be
convenient to have a sufficiently complex example to typecheck. The
following standard sequence of types and functions suits this goal.</p>
<figure class='code'><figcaption><span>Functions using Pattern Matching</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/Standard.agda#L34-L52'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="err">ℕ</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">zero</span> <span class="kt">:</span> <span class="err">ℕ</span>
</span><span class='line'> <span class="n">suc</span> <span class="kt">:</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="err">→</span> <span class="err">ℕ</span>
</span><span class='line'>
</span><span class='line'><span class="kr">data</span> <span class="kt">Vec</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="kt">Set</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">nil</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">zero</span>
</span><span class='line'> <span class="n">cons</span> <span class="kt">:</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">add</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span>
</span><span class='line'><span class="nf">add</span> <span class="n">zero</span> <span class="n">n</span> <span class="ow">=</span> <span class="n">n</span>
</span><span class='line'><span class="nf">add</span> <span class="p">(</span><span class="n">suc</span> <span class="n">m</span><span class="p">)</span> <span class="n">n</span> <span class="ow">=</span> <span class="n">suc</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">mult</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span>
</span><span class='line'><span class="nf">mult</span> <span class="n">zero</span> <span class="n">n</span> <span class="ow">=</span> <span class="n">zero</span>
</span><span class='line'><span class="nf">mult</span> <span class="p">(</span><span class="n">suc</span> <span class="n">m</span><span class="p">)</span> <span class="n">n</span> <span class="ow">=</span> <span class="n">add</span> <span class="n">n</span> <span class="p">(</span><span class="n">mult</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">append</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">m</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">ys</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'><span class="nf">append</span> <span class="kt">A</span> <span class="o">.</span><span class="n">zero</span> <span class="n">nil</span> <span class="n">n</span> <span class="n">ys</span> <span class="ow">=</span> <span class="n">ys</span>
</span><span class='line'><span class="nf">append</span> <span class="kt">A</span> <span class="o">.</span><span class="p">(</span><span class="n">suc</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="n">cons</span> <span class="n">m</span> <span class="n">x</span> <span class="n">xs</span><span class="p">)</span> <span class="n">n</span> <span class="n">ys</span> <span class="ow">=</span> <span class="n">cons</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span> <span class="n">x</span> <span class="p">(</span><span class="n">append</span> <span class="kt">A</span> <span class="n">m</span> <span class="n">xs</span> <span class="n">n</span> <span class="n">ys</span><span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">concat</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">m</span> <span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">xss</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="p">(</span><span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">)</span>
</span><span class='line'><span class="nf">concat</span> <span class="kt">A</span> <span class="n">m</span> <span class="o">.</span><span class="n">zero</span> <span class="n">nil</span> <span class="ow">=</span> <span class="n">nil</span>
</span><span class='line'><span class="nf">concat</span> <span class="kt">A</span> <span class="n">m</span> <span class="o">.</span><span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="n">cons</span> <span class="n">n</span> <span class="n">xs</span> <span class="n">xss</span><span class="p">)</span> <span class="ow">=</span> <span class="n">append</span> <span class="kt">A</span> <span class="n">m</span> <span class="n">xs</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="n">concat</span> <span class="kt">A</span> <span class="n">m</span> <span class="n">n</span> <span class="n">xss</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>This sequence of functions has the nice property that each function
builds upon the previous ones (either in its type, value, or both),
ending in the definition of <code>concat</code>. Furthemore, concat has
a moderatley complicated dependent type, but only eliminates type
families applied to a sequence of variables. Eliminating type families
applied to expressions built from constructors requires more clever motive synthesis
(via <a href="http://strictlypositive.org/goguen.pdf">Eliminating Dependent Pattern Matching</a>
by Goguen et. al.) that I would like to ignore for this first pass.</p>
<h2>Eliminators</h2>
<p>Translating these basic functions into eliminators is straightforward.
Because we only eliminate type families applied to a sequence
of variables, the branch functions supplied to the eliminator look like
pattern matching, and the whole definition is rather compact.</p>
<figure class='code'><figcaption><span>Functions using Eliminators</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/Standard.agda#L54-L76'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">add</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span>
</span><span class='line'><span class="nf">add</span> <span class="ow">=</span> <span class="n">elim</span><span class="err">ℕ</span> <span class="p">(</span><span class="err">λ</span> <span class="kr">_</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">n</span> <span class="err">→</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">m</span> <span class="n">ih</span> <span class="n">n</span> <span class="err">→</span> <span class="n">suc</span> <span class="p">(</span><span class="n">ih</span> <span class="n">n</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="nf">mult</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span>
</span><span class='line'><span class="nf">mult</span> <span class="ow">=</span> <span class="n">elim</span><span class="err">ℕ</span> <span class="p">(</span><span class="err">λ</span> <span class="kr">_</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="err">→</span> <span class="err">ℕ</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">n</span> <span class="err">→</span> <span class="n">zero</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">m</span> <span class="n">ih</span> <span class="n">n</span> <span class="err">→</span> <span class="n">add</span> <span class="n">n</span> <span class="p">(</span><span class="n">ih</span> <span class="n">n</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="nf">append</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">m</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">ys</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'><span class="nf">append</span> <span class="kt">A</span> <span class="ow">=</span> <span class="n">elimVec</span> <span class="kt">A</span> <span class="p">(</span><span class="err">λ</span> <span class="n">m</span> <span class="n">xs</span> <span class="err">→</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">ys</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">))</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">n</span> <span class="n">ys</span> <span class="err">→</span> <span class="n">ys</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">m</span> <span class="n">x</span> <span class="n">xs</span> <span class="n">ih</span> <span class="n">n</span> <span class="n">ys</span> <span class="err">→</span> <span class="n">cons</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span> <span class="n">x</span> <span class="p">(</span><span class="n">ih</span> <span class="n">n</span> <span class="n">ys</span><span class="p">))</span>
</span><span class='line'>
</span><span class='line'><span class="nf">concat</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">m</span> <span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="p">)</span> <span class="p">(</span><span class="n">xss</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="p">(</span><span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">)</span>
</span><span class='line'><span class="nf">concat</span> <span class="kt">A</span> <span class="n">m</span> <span class="ow">=</span> <span class="n">elimVec</span> <span class="p">(</span><span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="err">λ</span> <span class="n">n</span> <span class="n">xss</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">))</span>
</span><span class='line'> <span class="n">nil</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span> <span class="n">n</span> <span class="n">xs</span> <span class="n">xss</span> <span class="n">ih</span> <span class="err">→</span> <span class="n">append</span> <span class="kt">A</span> <span class="n">m</span> <span class="n">xs</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">)</span> <span class="n">ih</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<h2>Computational Descriptions</h2>
<p>Now we will consider <code>Desc</code>riptions as they appear in
<a href="http://gallium.inria.fr/~pdagand/stuffs/thesis-2011-phd/thesis.pdf">Dagand’s thesis</a>,
which are the core type theory analogue to surface language datatype
definitions.</p>
<figure class='code'><figcaption><span>Computational Description Datatypes</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/ComputationalDesc.agda#L19-L20'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">Desc</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span><span class="err">₁</span> <span class="kr">where</span>
</span><span class='line'> <span class="p">`</span><span class="err">⊤</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'> <span class="p">`</span><span class="kt">X</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'> <span class="p">`</span><span class="err">Σ</span> <span class="p">`</span><span class="err">Π</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'>
</span><span class='line'><span class="kt">El</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="kt">X</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Set</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">`</span><span class="err">⊤</span> <span class="kt">X</span> <span class="ow">=</span> <span class="err">⊤</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="kt">X</span> <span class="n">i</span><span class="p">)</span> <span class="kt">X</span> <span class="ow">=</span> <span class="kt">X</span> <span class="n">i</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="err">Σ</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="ow">=</span> <span class="err">Σ</span> <span class="kt">A</span> <span class="p">(</span><span class="err">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">El</span> <span class="kt">I</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">X</span><span class="p">)</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="err">Π</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="ow">=</span> <span class="p">(</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">El</span> <span class="kt">I</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">X</span>
</span><span class='line'>
</span><span class='line'><span class="kr">data</span> <span class="err">μ</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">R</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">con</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">I</span> <span class="p">(</span><span class="kt">R</span> <span class="n">i</span><span class="p">)</span> <span class="p">(</span><span class="err">μ</span> <span class="kt">I</span> <span class="kt">R</span><span class="p">)</span> <span class="err">→</span> <span class="err">μ</span> <span class="kt">I</span> <span class="kt">R</span> <span class="n">i</span>
</span></code></pre></td></tr></table></div></figure>
<p>A well known isomorphism exists between sums and dependent products
whose domain is some finite collection. To encode a type such as <code>ℕ</code>,
we can use a <code>Σ</code> whose domain is an index into an enumeration of the
contructor names <code>zero</code> and <code>suc</code>.</p>
<figure class='code'><figcaption><span>Computational ℕ Declaration</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/ComputationalDesc.agda#L57-L67'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="err">ℕ</span><span class="kt">T</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span> <span class="p">`</span><span class="n">zero</span> <span class="p">`</span><span class="n">suc</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="kt">T</span>
</span><span class='line'>
</span><span class='line'><span class="err">ℕ</span><span class="kt">D</span> <span class="kt">:</span> <span class="err">⊤</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="err">⊤</span>
</span><span class='line'><span class="err">ℕ</span><span class="kt">D</span> <span class="n">tt</span> <span class="ow">=</span> <span class="p">`</span><span class="err">Σ</span> <span class="err">ℕ</span><span class="kt">T</span> <span class="err">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="p">`</span><span class="n">zero</span> <span class="err">→</span> <span class="p">`</span><span class="err">⊤</span>
</span><span class='line'> <span class="p">;</span> <span class="p">`</span><span class="n">suc</span> <span class="err">→</span> <span class="p">`</span><span class="kt">X</span> <span class="n">tt</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>
</span><span class='line'><span class="err">ℕ</span> <span class="kt">:</span> <span class="err">⊤</span> <span class="err">→</span> <span class="kt">Set</span>
</span><span class='line'><span class="err">ℕ</span> <span class="ow">=</span> <span class="err">μ</span> <span class="err">⊤</span> <span class="err">ℕ</span><span class="kt">D</span>
</span></code></pre></td></tr></table></div></figure>
<p>If you’ve been reading carefully, you noticed that <code>μ</code> did not take a
<code>Desc</code>ription as an argument, but a function from the index to a
description. Certain type families can be defined computationally (as
functions from their index), as in
<a href="http://eb.host.cs.st-andrews.ac.uk/writings/types2003.pdf">Inductive Families Need Not Store Their Indices</a>
by Brady et. al. Eliminating functions defined in this style leads to
particularly nice reduction behaviour, buying you free equations
thanks to definitional equality. <code>ℕ</code> was not indexed, but below is an
example of defining <code>Vec</code> as a computational description.</p>
<figure class='code'><figcaption><span>Computational Vec Declaration</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/ComputationalDesc.agda#L77-L82'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">VecT</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span> <span class="p">`</span><span class="n">nil</span> <span class="p">`</span><span class="n">cons</span> <span class="kt">:</span> <span class="kt">VecT</span>
</span><span class='line'>
</span><span class='line'><span class="kt">VecD</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="p">(</span><span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span>
</span><span class='line'><span class="kt">VecD</span> <span class="kt">A</span> <span class="n">zero</span> <span class="ow">=</span> <span class="p">`</span><span class="err">⊤</span>
</span><span class='line'><span class="kt">VecD</span> <span class="kt">A</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="ow">=</span> <span class="p">`</span><span class="err">Σ</span> <span class="kt">A</span> <span class="err">λ</span> <span class="kr">_</span> <span class="err">→</span> <span class="p">`</span><span class="kt">X</span> <span class="n">n</span>
</span><span class='line'>
</span><span class='line'><span class="kt">Vec</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Set</span>
</span><span class='line'><span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span> <span class="ow">=</span> <span class="err">μ</span> <span class="p">(</span><span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="kt">VecD</span> <span class="kt">A</span><span class="p">)</span> <span class="n">n</span>
</span></code></pre></td></tr></table></div></figure>
<p>Rather than using a standard eliminator on datatypes defined using
descriptions, the special <code>ind</code> elimination rule is used. An
eliminator has separate “branches” for each constructor of a datatype,
along with proofs of the motive being satisfied at recursive positions
in the constructor. Intead, <code>ind</code> has a single branch (called <code>pcon</code>
below) that bundles up all branches of a typical eliminator, along
with an <code>All</code> argument for all recursive motive proofs.</p>
<figure class='code'><figcaption><span>ind Elimination Rule Type</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/ComputationalDesc.agda#L30-L37'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">ind</span> <span class="kt">:</span>
</span><span class='line'> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="kt">R</span> <span class="kt">:</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="kt">P</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="err">μ</span> <span class="kt">I</span> <span class="kt">R</span> <span class="n">i</span> <span class="err">→</span> <span class="kt">Set</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="n">pcon</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">I</span> <span class="p">(</span><span class="kt">R</span> <span class="n">i</span><span class="p">)</span> <span class="p">(</span><span class="err">μ</span> <span class="kt">I</span> <span class="kt">R</span><span class="p">))</span> <span class="err">→</span> <span class="kt">All</span> <span class="kt">I</span> <span class="p">(</span><span class="err">μ</span> <span class="kt">I</span> <span class="kt">R</span><span class="p">)</span> <span class="p">(</span><span class="kt">R</span> <span class="n">i</span><span class="p">)</span> <span class="n">xs</span> <span class="kt">P</span> <span class="err">→</span> <span class="kt">P</span> <span class="n">i</span> <span class="p">(</span><span class="n">con</span> <span class="n">xs</span><span class="p">))</span>
</span><span class='line'> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="n">x</span> <span class="kt">:</span> <span class="err">μ</span> <span class="kt">I</span> <span class="kt">R</span> <span class="n">i</span><span class="p">)</span>
</span><span class='line'> <span class="err">→</span> <span class="kt">P</span> <span class="n">i</span> <span class="n">x</span>
</span></code></pre></td></tr></table></div></figure>
<p>Using this eliminator we can define our running example of function
definitions. Here we use <code>ind</code> rather than pattern matching. The
anonymous function argument represents sugared “{}” syntax from
Dagand thesis <code>Example 3.19</code>. Additionally, the arguments bound in each
constructor pattern match clause are desugared into projections on the
right hand side. We will see what the final desugared terms look like
later in this post.</p>
<figure class='code'><figcaption><span>Computational Desc Functions</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/ComputationalDesc.agda#L92-L124'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="nf">add</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span>
</span><span class='line'><span class="nf">add</span> <span class="ow">=</span> <span class="n">ind</span> <span class="err">⊤</span> <span class="err">ℕ</span><span class="kt">D</span> <span class="p">(</span><span class="err">λ</span> <span class="kr">_</span> <span class="kr">_</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="n">tt</span> <span class="p">(`</span><span class="n">zero</span> <span class="p">,</span> <span class="n">tt</span><span class="p">)</span> <span class="n">tt</span> <span class="n">n</span> <span class="err">→</span> <span class="n">n</span>
</span><span class='line'> <span class="p">;</span> <span class="n">tt</span> <span class="p">(`</span><span class="n">suc</span> <span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="n">ih</span> <span class="n">n</span> <span class="err">→</span> <span class="n">suc</span> <span class="p">(</span><span class="n">ih</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">)</span>
</span><span class='line'> <span class="n">tt</span>
</span><span class='line'>
</span><span class='line'><span class="nf">mult</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span>
</span><span class='line'><span class="nf">mult</span> <span class="ow">=</span> <span class="n">ind</span> <span class="err">⊤</span> <span class="err">ℕ</span><span class="kt">D</span> <span class="p">(</span><span class="err">λ</span> <span class="kr">_</span> <span class="kr">_</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span> <span class="err">→</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="n">tt</span> <span class="p">(`</span><span class="n">zero</span> <span class="p">,</span> <span class="n">tt</span><span class="p">)</span> <span class="n">tt</span> <span class="n">n</span> <span class="err">→</span> <span class="n">zero</span>
</span><span class='line'> <span class="p">;</span> <span class="n">tt</span> <span class="p">(`</span><span class="n">suc</span> <span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="n">ih</span> <span class="n">n</span> <span class="err">→</span> <span class="n">add</span> <span class="n">n</span> <span class="p">(</span><span class="n">ih</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">)</span>
</span><span class='line'> <span class="n">tt</span>
</span><span class='line'>
</span><span class='line'><span class="nf">append</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">m</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="n">ys</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span>
</span><span class='line'><span class="nf">append</span> <span class="kt">A</span> <span class="ow">=</span> <span class="n">ind</span> <span class="p">(</span><span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="kt">VecD</span> <span class="kt">A</span><span class="p">)</span> <span class="p">(</span><span class="err">λ</span> <span class="n">m</span> <span class="n">xs</span> <span class="err">→</span> <span class="p">(</span><span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="n">ys</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">))</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="n">zero</span> <span class="n">tt</span> <span class="n">tt</span> <span class="n">n</span> <span class="n">ys</span> <span class="err">→</span> <span class="n">ys</span>
</span><span class='line'> <span class="p">;</span> <span class="p">(</span><span class="n">suc</span> <span class="n">m</span><span class="p">)</span> <span class="p">(</span><span class="n">x</span> <span class="p">,</span> <span class="n">xs</span><span class="p">)</span> <span class="n">ih</span> <span class="n">n</span> <span class="n">ys</span> <span class="err">→</span> <span class="n">cons</span> <span class="kt">A</span> <span class="p">(</span><span class="n">add</span> <span class="n">m</span> <span class="n">n</span><span class="p">)</span> <span class="n">x</span> <span class="p">(</span><span class="n">ih</span> <span class="n">n</span> <span class="n">ys</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">)</span>
</span><span class='line'>
</span><span class='line'><span class="nf">concat</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="n">m</span> <span class="n">n</span> <span class="kt">:</span> <span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="n">xss</span> <span class="kt">:</span> <span class="kt">Vec</span> <span class="p">(</span><span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">)</span> <span class="n">n</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">)</span>
</span><span class='line'><span class="nf">concat</span> <span class="kt">A</span> <span class="n">m</span> <span class="ow">=</span> <span class="n">ind</span> <span class="p">(</span><span class="err">ℕ</span> <span class="n">tt</span><span class="p">)</span> <span class="p">(</span><span class="kt">VecD</span> <span class="p">(</span><span class="kt">Vec</span> <span class="kt">A</span> <span class="n">m</span><span class="p">))</span> <span class="p">(</span><span class="err">λ</span> <span class="n">n</span> <span class="n">xss</span> <span class="err">→</span> <span class="kt">Vec</span> <span class="kt">A</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">))</span>
</span><span class='line'> <span class="p">(</span><span class="err">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="n">zero</span> <span class="n">tt</span> <span class="n">tt</span> <span class="err">→</span> <span class="n">nil</span> <span class="kt">A</span>
</span><span class='line'> <span class="p">;</span> <span class="p">(</span><span class="n">suc</span> <span class="n">n</span><span class="p">)</span> <span class="p">(</span><span class="n">xs</span> <span class="p">,</span> <span class="n">xss</span><span class="p">)</span> <span class="n">ih</span> <span class="err">→</span> <span class="n">append</span> <span class="kt">A</span> <span class="n">m</span> <span class="n">xs</span> <span class="p">(</span><span class="n">mult</span> <span class="n">n</span> <span class="n">m</span><span class="p">)</span> <span class="n">ih</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'> <span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>
<p>Definitions using computational descriptions (like the ones above) are
nice because you can pattern match on the index (e.g. <code>ℕ</code>) and the
description for the type family (e.g. <code>Vec</code>) definitionally unfolds.
However, things get a bit clunkier once we wish to support named
constructor arguments. Notice that we defined <code>ℕ</code> with an enumeration
for the constructor arguments, but we did not do the same for <code>Vec</code>.
<code>Example 7.46</code> in Dagand shows how to elaborate <code>Vec</code> into a description
that has named constructor arguments. This involves first wrapping the
description in an <code>elim</code> constructor to identify <code>Vec</code> as a type defined
by computation over its index. Then, the <code>zero</code> and <code>suc</code> branches
return <code>zero</code> and <code>suc</code> constructor tags respectively. In this case,
the constructors index into singleton enumerations, i.e. <code>elim</code> into
<code>[elim]</code>, <code>zero</code> into <code>[zero]</code>, and <code>suc</code> into <code>[suc]</code>. If we were
defining a type that had multiple constructors with the same index for
a particular index branch then the enumeration would not
be a singleton, but it would still only be sub-enumeration of the
total enumeration of constructors that we have in mind for the type.</p>
<p>In contrast,
the <code>ℕ</code> description tag constructors both belong to a more natural
enumeration, i.e. <code>zero</code> and <code>suc</code> index into <code>[zero, suc]</code>. Hence,
although functions like <code>append</code> and <code>concat</code> defined above over
computational description <code>Vec</code> look nice, once you add these
singleton tags and desugar everything, you get lots of eliminations
over singleton enumerations that are IMO no longer as elegant.
Additionally, type families defined by computation over the index are
only a subclass of all possible type families. The remaining types
(and actually, all type families) can be alternatively defined by
constraining the index with a propositional equality proof. See Dagand
<code>Example 7.45</code> for how to define <code>Vec</code> this way. This type of definition
keeps the more natural enumeration of constructor tags. I will call
types defined this way “propositional descriptions”.</p>
<h2>Propositional Descriptions</h2>
<p>Although computational descriptions give you an additional way to
define types, in practice once you add named constructors and perform
elaboration of patterns to eliminators, I don’t feel like they buy you
enough for the additional complexity. I am content with supporting
Agda-style propositionally defined datatypes exclusively. Given this
decision, we can change the grammar of descriptions to more
closely resemble the surface language Agda-style datatype
declarations. I saw something like this alternative <code>Desc</code> definition
from the code accompanying a
<a href="http://perso.ens-lyon.fr/guillaume.allais/?en/main/blog/read/syntax-binding-run-omega">blog post</a>
by Guillaume Allais.</p>
<figure class='code'><figcaption><span>Propositional Description Datatypes</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/PropositionalDesc.agda#L38-L54'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'><span class="kr">data</span> <span class="kt">Desc</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span><span class="err">₁</span> <span class="kr">where</span>
</span><span class='line'> <span class="p">`</span><span class="kt">End</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'> <span class="p">`</span><span class="kt">Rec</span> <span class="kt">:</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'> <span class="p">`</span><span class="kt">Arg</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'> <span class="p">`</span><span class="kt">RecFun</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">A</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">B</span> <span class="kt">:</span> <span class="kt">A</span> <span class="err">→</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">Desc</span> <span class="kt">I</span>
</span><span class='line'>
</span><span class='line'><span class="kt">ISet</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="err">→</span> <span class="kt">Set</span><span class="err">₁</span>
</span><span class='line'><span class="kt">ISet</span> <span class="kt">I</span> <span class="ow">=</span> <span class="kt">I</span> <span class="err">→</span> <span class="kt">Set</span>
</span><span class='line'>
</span><span class='line'><span class="kt">El</span> <span class="kt">:</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="kt">X</span> <span class="kt">:</span> <span class="kt">ISet</span> <span class="kt">I</span><span class="p">)</span> <span class="err">→</span> <span class="kt">ISet</span> <span class="kt">I</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="kt">End</span> <span class="n">j</span><span class="p">)</span> <span class="kt">X</span> <span class="n">i</span> <span class="ow">=</span> <span class="n">j</span> <span class="err">≡</span> <span class="n">i</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="kt">Rec</span> <span class="n">j</span> <span class="kt">D</span><span class="p">)</span> <span class="kt">X</span> <span class="n">i</span> <span class="ow">=</span> <span class="kt">X</span> <span class="n">j</span> <span class="err">×</span> <span class="kt">El</span> <span class="kt">I</span> <span class="kt">D</span> <span class="kt">X</span> <span class="n">i</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="kt">Arg</span> <span class="kt">A</span> <span class="kt">B</span><span class="p">)</span> <span class="kt">X</span> <span class="n">i</span> <span class="ow">=</span> <span class="err">Σ</span> <span class="kt">A</span> <span class="p">(</span><span class="err">λ</span> <span class="n">a</span> <span class="err">→</span> <span class="kt">El</span> <span class="kt">I</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">)</span> <span class="kt">X</span> <span class="n">i</span><span class="p">)</span>
</span><span class='line'><span class="kt">El</span> <span class="kt">I</span> <span class="p">(`</span><span class="kt">RecFun</span> <span class="kt">A</span> <span class="kt">B</span> <span class="kt">D</span><span class="p">)</span> <span class="kt">X</span> <span class="n">i</span> <span class="ow">=</span> <span class="p">((</span><span class="n">a</span> <span class="kt">:</span> <span class="kt">A</span><span class="p">)</span> <span class="err">→</span> <span class="kt">X</span> <span class="p">(</span><span class="kt">B</span> <span class="n">a</span><span class="p">))</span> <span class="err">×</span> <span class="kt">El</span> <span class="kt">I</span> <span class="kt">D</span> <span class="kt">X</span> <span class="n">i</span>
</span><span class='line'>
</span><span class='line'><span class="kr">data</span> <span class="err">μ</span> <span class="p">(</span><span class="kt">I</span> <span class="kt">:</span> <span class="kt">Set</span><span class="p">)</span> <span class="p">(</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="kt">I</span><span class="p">)</span> <span class="p">(</span><span class="n">i</span> <span class="kt">:</span> <span class="kt">I</span><span class="p">)</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span>
</span><span class='line'> <span class="n">con</span> <span class="kt">:</span> <span class="kt">El</span> <span class="kt">I</span> <span class="kt">D</span> <span class="p">(</span><span class="err">μ</span> <span class="kt">I</span> <span class="kt">D</span><span class="p">)</span> <span class="n">i</span> <span class="err">→</span> <span class="err">μ</span> <span class="kt">I</span> <span class="kt">D</span> <span class="n">i</span>
</span></code></pre></td></tr></table></div></figure>
<p>This description grammar enforces descriptions to look like what we
are used to seeing in datatype declarations. For example,
<code>Rec/Arg/RecFun</code>, corresponding to the previous <code>X/Σ/Π</code> constructors,
take an extra
description argument at the end. Then <code>End</code>, formerly <code>⊤</code>, ends the
“constructor” with an index value. The interpretation function uses
this index value to ask for a propositionally equality proof, making
sure that the index of the constructor you produce matches the index
of the type you specified. This can be achieved in the previous <code>Desc</code>
grammar by ending a description with <code>Σ (x ≡ y) λ _ → ⊤</code>, but here
that pattern is internalized. One pleasant consequence can be seen by
looking at the <code>μ</code> datatype. It no longer requires a function from the
index to a description, and now merely requires a description. Because
we no longer support computational described datatypes (instead
describing them all propositionally), our descriptions can be
first-order rather than higher-order. The more first-order your
descriptions are, the more
<a href="https://github.com/larrytheliquid/leveling-up">fully generic programming</a>
you can do over them.</p>
<p>The <code>ℕ</code> datatype is declared pretty much the same as before. However,
<code>Vec</code> is now given with its constructor names, and the index of a
particular constructor is given at the end of the sequence of
constructor arguments. Compare this to the Agda data declaration at
the top of the post and notice the similar structure.</p>
<figure class='code'><figcaption><span>Propositional ℕ & Vec Declarations</span><a href='https://github.com/spire/spire/blob/b4f467da96d5de9050f58b41ac10fd9a73ac84df/formalization/agda/Spire/Examples/PropositionalDesc.agda#L97-L122'>link</a></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
</pre></td><td class='code'><pre><code class='haskell'><span class='line'> <span class="kr">data</span> <span class="err">ℕ</span><span class="kt">T</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span> <span class="p">`</span><span class="n">zero</span> <span class="p">`</span><span class="n">suc</span> <span class="kt">:</span> <span class="err">ℕ</span><span class="kt">T</span>
</span><span class='line'> <span class="kr">data</span> <span class="kt">VecT</span> <span class="kt">:</span> <span class="kt">Set</span> <span class="kr">where</span> <span class="p">`</span><span class="n">nil</span> <span class="p">`</span><span class="n">cons</span> <span class="kt">:</span> <span class="kt">VecT</span>
</span><span class='line'>
</span><span class='line'> <span class="err">ℕ</span><span class="kt">D</span> <span class="kt">:</span> <span class="kt">Desc</span> <span class="err">⊤</span>
</span><span class='line'> <span class="err">ℕ</span><span class="kt">D</span> <span class="ow">=</span> <span class="p">`</span><span class="kt">Arg</span> <span class="err">ℕ</span><span class="kt">T</span> <span class="err">λ</span>
</span><span class='line'> <span class="p">{</span> <span class="p">`</span><span class="n">zero</span> <span class="err">→</span> <span class="p">`</span><span class="kt">End</span> <span class="n">tt</span>
</span><span class='line'> <span class="p">;</span> <span class="p">`</span><span class="n">suc</span> <span class="err">→</span> <span class="p">`</span><span class="kt">Rec</span> <span class="n">tt</span> <span class="p">(`</span><span class="kt">End</span> <span class="n">tt</span><span class="p">)</span>
</span><span class='line'> <span class="p">}</span>
</span><span class='line'>