-
Notifications
You must be signed in to change notification settings - Fork 1
/
upi.lagda
1857 lines (1575 loc) Β· 78 KB
/
upi.lagda
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass{entcs}
\usepackage{prentcsmacro}
\def\lastname{Carette, Chen, Choudhury, and Sabry}
%% Amr
%% words to remember :-)
%% sublime unfathomable
%% path categorical semantics
%% ---
\usepackage{bbold}
\usepackage{bussproofs}
\usepackage{keystroke}
\usepackage{comment}
\usepackage{tikz}
\usepackage[inline]{enumitem}
\usepackage{stmaryrd}
\usepackage[conor]{agda}
\usepackage[mathscr]{euscript}
\usepackage[euler]{textgreek}
\usepackage{mathabx}
\usepackage{isomath}
\usepackage{microtype}
\usepackage{etoolbox}
\makeatletter
\newcommand*\NoIndentAfterEnv[1]{%
\AfterEndEnvironment{#1}{\par\@afterindentfalse\@afterheading}}
\makeatother
\NoIndentAfterEnv{code}
\NoIndentAfterEnv{figure}
\DeclareUnicodeCharacter{120793}{$\mathbb{1}$}
\DeclareUnicodeCharacter{120794}{$\mathbb{2}$}
\DeclareUnicodeCharacter{9726}{$\sqbullet$}
\DeclareUnicodeCharacter{120792}{$\mathbb{0}$}
\DeclareUnicodeCharacter{119932}{$\mathbfit{U}$}
\DeclareUnicodeCharacter{119984}{$\mathcal{U}$}
\DeclareUnicodeCharacter{8988}{$\ulcorner$}
\DeclareUnicodeCharacter{8989}{$\urcorner$}
% \newcommand{\byiso}[1]{{\leftrightarrow}{\langle} ~#1~ \rangle}
% \newcommand{\byisotwo}[1]{{\Leftrightarrow}{\langle} ~#1~ \rangle}
\newcommand{\byiso}[1]{{\leftrightarrowβ}{\langle} ~#1~ \rangle}
\newcommand{\byisotwo}[1]{{\leftrightarrowβ}{\langle} ~#1~ \rangle}
\newcommand{\unitepl}{\texttt{unitepl}}
\newcommand{\unitipl}{\texttt{unitipl}}
\newcommand{\unitepr}{\texttt{unitepr}}
\newcommand{\unitipr}{\texttt{unitipr}}
\newcommand{\swap}{\textit{swap}}
\newcommand{\swapp}{\texttt{swapp}}
\newcommand{\assoclp}{\texttt{assoclp}}
\newcommand{\assocrp}{\texttt{assocrp}}
\newcommand{\unitetl}{\texttt{unitetl}}
\newcommand{\unititl}{\texttt{unititl}}
\newcommand{\unitetr}{\texttt{unitetr}}
\newcommand{\unititr}{\texttt{unititr}}
\newcommand{\swapt}{\texttt{swapt}}
\newcommand{\assoclt}{\texttt{assoclt}}
\newcommand{\assocrt}{\texttt{assocrt}}
\newcommand{\absorbr}{\texttt{absorbr}}
\newcommand{\absorbl}{\texttt{absorbl}}
\newcommand{\factorzr}{\texttt{factorzr}}
\newcommand{\factorzl}{\texttt{factorzl}}
\newcommand{\factor}{\texttt{factor}}
\newcommand{\distl}{\texttt{distl}}
\newcommand{\dist}{\texttt{dist}}
\newcommand{\factorl}{\texttt{factorl}}
\newcommand{\id}{\textit{id}}
\newcommand{\compc}[2]{#1 \circ #2}
\newcommand{\compcc}[2]{#1 \bullet #2}
\newcommand{\respcomp}[2]{#1 \odot #2}
\newcommand{\trunc}{\textit{trunc}}
\newcommand{\Typ}{\mathbf{Type}}
\newcommand{\alt}{~\mid~}
\newcommand{\patht}[1]{\textsc{PATHS}(#1,#1)}
\newcommand{\fpatht}[1]{\textsc{FREEPATHS}(#1,\Box)}
\newcommand{\fpathp}[2]{\textsc{freepath}~#1~#2}
\newcommand{\pathind}[2]{\textsc{pathind}~#1~#2}
\newcommand{\invc}[1]{!\;#1}
\newcommand{\evalone}[2]{eval(#1,#2)}
\newcommand{\evalbone}[2]{evalB(#1,#2)}
\newcommand{\reflp}{\textsc{refl}}
\newcommand{\notp}{\textsc{not}}
\newcommand{\gluep}{\textsc{glue}}
\newcommand{\reflh}{\mathit{refl}_{\sim}}
\newcommand{\symh}[1]{\mathit{sym}_{\sim}~#1}
\newcommand{\transh}[2]{\mathit{trans}_{\sim}~#1~#2}
\newcommand{\reflq}{\mathit{refl}_{\simeq}}
\newcommand{\symq}[1]{\mathit{sym}_{\simeq}~#1}
\newcommand{\transq}[2]{\mathit{trans}_{\simeq}~#1~#2}
\newcommand{\isequiv}[1]{\mathit{isequiv}(#1)}
\newcommand{\idc}{\mathit{id}_{\boolt}}
\newcommand{\swapc}{\mathit{swap}_{\boolt}}
\newcommand{\assocc}{\mathit{assoc}}
\newcommand{\invl}{\mathit{invl}}
\newcommand{\invr}{\mathit{invr}}
\newcommand{\invinv}{\mathit{inv}^2}
\newcommand{\idlc}{\mathit{idl}}
\newcommand{\idrc}{\mathit{idr}}
\newcommand{\swapswap}{\swapc^2}
\newcommand{\compsim}{\compc_{\isotwo}}
% \newcommand{\iso}{\leftrightarrow}
% \newcommand{\isotwo}{\Leftrightarrow}
\newcommand{\iso}{\leftrightarrowβ}
\newcommand{\isotwo}{\leftrightarrowβ}
\newcommand{\isothree}{\leftrightarrowβ}
\newcommand{\piso}{\multimapdotbothB~~}
\newcommand{\zt}{\mathbb{0}}
\newcommand{\ot}{\mathbb{1}}
\newcommand{\bt}{\mathbb{2}}
\newcommand{\fc}{\mathit{false}}
\newcommand{\tc}{\mathit{true}}
\newcommand{\boolt}{\mathbb{B}}
\newcommand{\univ}{\mathcal{U}}
\newcommand{\uzero}{\mathcal{U}_0}
\newcommand{\uone}{\mathcal{U}_1}
\newcommand{\Rule}[2]{
\makebox{
$\displaystyle
\frac{\begin{array}{l}#1\\\end{array}}
{\begin{array}{l}#2\\\end{array}}$}}
\newcommand{\proves}{\vdash}
\newcommand{\jdgg}[3]{#1 \proves #2 : #3}
\newcommand{\jdg}[2]{\proves #1 : #2}
\newcommand{\jdge}[3]{\proves #1 = #2 : #3}
%% codes
%% denotations
% TODO: give this a better name!
\newcommand{\bracket}[1]{\ensuremath{\{#1\}}}
\newcommand{\ptrunc}[1]{\ensuremath{\| #1 \|}}
\newcommand{\dbracket}[1]{\ensuremath{\llbracket \; #1 \; \rrbracket}}
\let\oldPi\Pi
\renewcommand{\Pi}{\mathrm\oldPi}
\newcommand{\PiTwo}{\ensuremath{\mathrm\Pi_{\mathbb{2}}}}
\newcommand{\amr}[1]{\fbox{\begin{minipage}{0.8\textwidth}\color{red}{Amr says: {#1}}\end{minipage}}}
\newcommand{\jacques}[1]{\fbox{\begin{minipage}{0.8\textwidth}\color{red}{Jacques says: {#1}}\end{minipage}}}
\newcommand{\newnote}[2]{{\sf {#1} $\clubsuit$ {#2} $\clubsuit$}}
\newcommand{\VC}[1]{{\color{orange}{\newnote{VC}{#1}}}}
\newcommand{\newtext}[1]{{\color{purple}{#1}}}
\begin{document}
\begin{frontmatter}
\title{From Reversible Programs to \\ Univalent Universes and Back}
\author{Jacques Carette}
\address{McMaster University}
\author{Chao-Hong Chen}
\author{Vikraman Choudhury}
\author{Amr Sabry}
\address{Indiana University}
\begin{abstract}
We establish a close connection between a reversible programming
language based on type isomorphisms and a formally presented
univalent universe. The correspondence relates combinators
witnessing type isomorphisms in the programming language to paths in
the univalent universe; and combinator optimizations in the
programming language to 2-paths in the univalent universe. The
result suggests a simple computational interpretation of paths and
of univalence in terms of familiar programming constructs whenever
the universe in question is computable.
\end{abstract}
\end{frontmatter}
\AgdaHide{
\begin{code}
{-# OPTIONS --without-K --type-in-type --allow-unsolved-metas #-}
module upi where
π° = Set
data β₯ : π° where
record β€ : π° where
constructor tt
record Ξ£ (A : π°) (B : A β π°) : π° where
constructor _,_
field
prβ : A
prβ : B prβ
open Ξ£ public
infixr 4 _,_
syntax Ξ£ A (Ξ» a β B) = Ξ£[ a βΆ A ] B
infix 2 _Γ_
_Γ_ : (A B : π°) β π°
A Γ B = Ξ£ A (Ξ» _ β B)
data _+_ (A B : π°) : π° where
inl : (x : A) β A + B
inr : (y : B) β A + B
Ξ : (A : π°) (B : A β π°) β π°
Ξ A B = (a : A) β B a
syntax Ξ A (Ξ» a β B) = Ξ [ a βΆ A ] B
id : {A : π°} β A β A
id a = a
infix 4 _β_
_β_ : {A : π°} {B : A β π°} {C : {a : A} β B a β π°}
β (g : {a : A} β (b : B a) β C b) (f : (a : A) β B a)
β (a : A) β C (f a)
g β f = Ξ» a β g (f a)
infix 3 _==_
data _==_ {A : π°} : A β A β π° where
refl : (a : A) β a == a
infix 100 !_
!_ : {A : π°} {a b : A} β (a == b) β (b == a)
!_ (refl _) = refl _
infixr 80 _βΎ_
_βΎ_ : {A : π°} {a b c : A} β (a == b) β (b == c) β (a == c)
_βΎ_ (refl _) (refl _) = refl _
infix 3 _βΌ_
_βΌ_ : {A : π°} {B : A β π°} (f g : (a : A) β B a) β π°
_βΌ_ {A} f g = (a : A) β f a == g a
coe : {A B : π°} (p : A == B) β A β B
coe (refl A) = id
ap : {A B : π°} {x y : A} β (f : A β B) (p : x == y) β f x == f y
ap f (refl x) = refl (f x)
transport : {A : π°} (P : A β π°) {x y : A} β x == y β P x β P y
transport P = coe β ap P
PathOver : {A : π°} (P : A β π°) {x y : A} (p : x == y) (u : P x) (v : P y) β π°
PathOver P p u v = transport P p u == v
syntax PathOver P p u v = u == v [ P β p ]
apd : {A : π°} {P : A β π°} {x y : A} (f : (a : A) β P a) (p : x == y) β f x == f y [ P β p ]
apd f (refl x) = refl (f x)
β₯-elim : {C : π°} β β₯ β C
β₯-elim ()
module _ {X : π°} where
βΎunitr : {x y : X} β (p : x == y) β p βΎ refl y == p
βΎunitr (refl x) = refl (refl x)
βΎunitl : {x y : X} β (p : x == y) β refl x βΎ p == p
βΎunitl (refl x) = refl (refl x)
βΎinvr : {x y : X} β (p : x == y) β ! p βΎ p == refl y
βΎinvr (refl x) = refl (refl x)
βΎinvl : {x y : X} β (p : x == y) β p βΎ ! p == refl x
βΎinvl (refl x) = refl (refl x)
!! : {x y : X} β (p : x == y) β ! (! p) == p
!! (refl x) = refl (refl x)
!βΎ : {x y z : X} β (p : x == y) β (q : y == z) β ! (p βΎ q) == ! q βΎ ! p
!βΎ (refl y) (refl .y) = refl (refl y)
infixr 80 _[1,0,2]_
_[1,0,2]_ : {x y z : X} β {r s : y == z}
β (p : x == y) β r == s β p βΎ r == p βΎ s
(refl y) [1,0,2] Ξ³ = βΎunitl _ βΎ Ξ³ βΎ ! (βΎunitl _)
βΎassoc : {w x y z : X} β (p : w == x) β (q : x == y) β (r : y == z)
β (p βΎ q) βΎ r == p βΎ q βΎ r
βΎassoc p q (refl y) = βΎunitr _ βΎ (p [1,0,2] ! (βΎunitr _))
infixr 80 _[2,0,1]_
_[2,0,1]_ : {x y z : X} β {p q : x == y}
β p == q β (r : y == z) β p βΎ r == q βΎ r
Ξ± [2,0,1] (refl y) = βΎunitr _ βΎ Ξ± βΎ ! (βΎunitr _)
infixr 80 _[2,0,2]_
_[2,0,2]_ : {x y z : X} β {p q : x == y} β {r s : y == z}
β p == q β r == s β p βΎ r == q βΎ s
_[2,0,2]_ {q = q} {r} Ξ± Ξ² = (Ξ± [2,0,1] r) βΎ (q [1,0,2] Ξ²)
\end{code}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Introduction}
The proceedings of the $2012$ Symposium on Principles of Programming
Languages~\cite{Field:2012:2103656} included two apparently unrelated papers:
\emph{Information Effects} by James and Sabry and \emph{Canonicity for
2-dimensional type theory} by Licata and Harper. The first paper, motivated by
the physical nature of
computation~\cite{Landauer:1961,PhysRevA.32.3266,Toffoli:1980,bennett1985fundamental,Frank:1999:REC:930275},
proposed, among other results, a reversible language $\Pi$ in which every
program is a type isomorphism. The second paper, motivated by the connections
between homotopy theory and type theory~\cite{vv06,hottbook}, proposed a
judgmental formulation of intensional dependent type theory with a
twice-iterated identity type. During the presentations and ensuing discussions
at the conference, it became apparent, at an intuitive and informal level, that
the two papers had strong similarities. Formalizing the precise connection was
far from obvious, however.
Here we report on a formal connection between appropriately formulated
reversible languages on one hand and univalent universes on the
other. In the next section, we give a rational reconstruction of the
reversible programming language $\Pi$, focusing on a small
``featherweight'' fragment~$\PiTwo$. In Sec.~\ref{sec:univalent}, we
review basic homotopy type theory (HoTT) background leading to
\emph{univalent fibrations} which allow us to give formal
presentations of ``small'' univalent universes. In
Sec.~\ref{sec:model} we define and establish the basic properties of
such a univalent subuniverse {\small\AgdaFunction{Ε¨[π]}} which we
prove in Sec.~\ref{sec:correspondence} as sound and complete with
respect to the reversible language $\PiTwo$.
Sec.~\ref{sec:discussion} discusses the implications of our work and
situates it into the broader context of the existing literature.
%% Sec.~\ref{sec:conclusion} right now is a stub, and may not
%% survive?
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{Reversible Programming Languages}
Starting from the physical principle of ``conservation of
information''~\cite{Hey:1999:FCE:304763,fredkin1982conservative}, James and
Sabry~\cite{James:2012:IE:2103656.2103667} proposed a family of programming
languages $\Pi$ in which computation preserves information. Technically,
computations are \emph{type isomorphisms} which, at least in the case of finite
types, clearly preserve entropy in the information-theoretic
sense~\cite{James:2012:IE:2103656.2103667}. We illustrate the general flavor of
the family of languages with some examples and then identify a ``featherweight''
version of $\Pi$, called $\PiTwo$, to use in our formal development.
%%%%%
\subsection{Examples}
The examples below assume a representation of the type of booleans
${\small\bt}$ as the disjoint union ${\small\ot \oplus \ot}$ with the
left injection representing ${\small\mathsf{false}}$ and the right
injection representing ${\small\mathsf{true}}$. Given an arbitrary
reversible function {\small\AgdaFunction{f}} of type
${\small a \iso a}$, we can build the reversible function
${\small\AgdaFunction{controlled}~\AgdaFunction{f}}$ that takes a pair
of type ${\small\bt \otimes a}$ and checks the incoming boolean; if it
is false (i.e., we are in the left injection), the function behaves
like the identity; otherwise the function applies {\small\AgdaFunction{f}}
to the second argument. The incoming boolean is then reconstituted to
maintain reversibility:
{\small
\[\def\arraystretch{1.2}\begin{array}{rcll}
\AgdaFunction{controlled} &:& \forall a.~ (a \iso a) \quad\rightarrow
& ~(\bt \otimes a \iso \bt \otimes a) \\
\AgdaFunction{controlled}~\AgdaFunction{f} &=&
\bt \otimes a
& \byiso{\AgdaFunction{unfoldBool} \otimes \AgdaFunction{id}} \\
&& (\ot \oplus \ot) \otimes a
& \byiso{\AgdaFunction{distribute}} \\
&& (\ot \otimes a) \oplus (\ot \otimes a)
& \byiso{\AgdaFunction{id} \oplus (\AgdaFunction{id} \otimes \AgdaFunction{f})} \\
&& (\ot \otimes a) \oplus (\ot \otimes a)
& \byiso{\AgdaFunction{factor}} \\
&& (\ot \oplus \ot) \otimes a
& \byiso{\AgdaFunction{foldBool} \otimes \AgdaFunction{id}} \\
&& \bt \otimes a & ~ \\
\end{array}
\]}
\noindent The left column shows the sequence of types that are visited
during the computation; the right column shows the names of the
combinators\footnote{We use names that are hopefully quite mnemonic;
for the precise definitions of the combinators see the
$\Pi$-papers~\cite{James:2012:IE:2103656.2103667,rc2011,rc2012,theseus,Carette2016}
or the accompanying code at
\url{https://git.io/v7wtW}.} that witness the
corresponding type isomorphism. The code for
{\small\AgdaFunction{controlled}~\AgdaFunction{f}} provides
constructive evidence (i.e., a program, a logic gate, or a hardware
circuit) for an automorphism on ${\small\bt \otimes a}$: it can be read
top-down or bottom-up to go back and forth.
The {\small\AgdaFunction{not}} function below is a simple lifting of
{\small\AgdaFunction{swapβ}} which swaps the left and right injections of a sum
type. Using the {\small\AgdaFunction{controlled}} building block, we can build a
controlled-not ({\small\AgdaFunction{cnot}}) gate and a controlled-controlled-not
gate, also known as the {\small\AgdaFunction{toffoli}} gate. The latter gate is a
universal function for combinational boolean circuits thus showing the
expressiveness of the language:
{\small
\[\begin{array}{rcl}
\AgdaFunction{not} &:& \bt \iso \bt \\
\AgdaFunction{not} &=&
\AgdaFunction{unfoldBool} \odot_1 \AgdaFunction{swapβ} \odot_1 \AgdaFunction{foldBool} \\
\\
\AgdaFunction{cnot} &:& \bt \otimes \bt \iso \bt \otimes \bt \\
\AgdaFunction{cnot} &=& \AgdaFunction{controlled}~\AgdaFunction{not} \\
\\
\AgdaFunction{toffoli} &:& \bt \otimes (\bt \otimes \bt)
\iso \bt \otimes (\bt \otimes \bt) \\
\AgdaFunction{toffoli} &=& \AgdaFunction{controlled}~\AgdaFunction{cnot} \\
\end{array}\]}
%%%
\noindent While we wrote {\small\AgdaFunction{controlled}} in
equational-reasoning style, {\small\AgdaFunction{not}} is written in
the point-free combinator style. These are equivalent as ${\small\byiso{-}}$
is defined in terms of the sequential composition combinator
${\small\odot_1}$.
As is customary in any semantic perspective on programming languages, we are
interested in the question of when two programs are ``equivalent.'' Consider the
following six programs of type~${\small\bt \iso \bt}$:
{\small
\[\def\arraystretch{1.2}\begin{array}{rcl}
\AgdaFunction{idβ}~\AgdaFunction{idβ}~\AgdaFunction{idβ}~
\AgdaFunction{notβ}~\AgdaFunction{notβ}~\AgdaFunction{notβ} &:& \bt \iso \bt \\
\AgdaFunction{idβ} &=&
\AgdaFunction{id} \odot_1 \AgdaFunction{id} \\
\AgdaFunction{idβ} &=&
\AgdaFunction{not} \odot_1 \AgdaFunction{id} \odot_1 \AgdaFunction{not} \\
\AgdaFunction{idβ} &=&
\AgdaFunction{unitiβ} \odot_1 \AgdaFunction{swapβ} \odot_1
(\AgdaFunction{id} \otimes \AgdaFunction{id}) \odot_1
\AgdaFunction{swapβ} \odot_1
\AgdaFunction{uniteβ} \\
\AgdaFunction{notβ} &=&
\AgdaFunction{id} \odot_1 \AgdaFunction{not} \\
\AgdaFunction{notβ} &=&
\AgdaFunction{not} \odot_1 \AgdaFunction{not} \odot_1 \AgdaFunction{not} \\
\AgdaFunction{notβ} &=&
\AgdaFunction{unitiβ} \odot_1 \AgdaFunction{swapβ} \odot_1
(\AgdaFunction{not} \otimes \AgdaFunction{id}) \odot_1
\AgdaFunction{swapβ} \odot_1
\AgdaFunction{uniteβ}
\end{array}\]}
\begin{figure}
\begin{center}
\begin{tikzpicture}[scale=0.9,every node/.style={scale=0.9}]
\draw (1,2) ellipse (0.5cm and 0.5cm);
\draw[fill] (1,2) circle [radius=0.025];
\node[below] at (1,2) {*};
\draw (0,0) ellipse (0.5cm and 1cm);
\draw[fill] (0,0.5) circle [radius=0.025];
\node[below] at (0,0.5) {F};
\draw[fill] (0,-0.5) circle [radius=0.025];
\node[below] at (0,-0.5) {T};
\draw (1,2) -- (2,2) ; %% ()
\draw (0,0.5) -- (2,0.5) ; %% F
\draw (0,-0.5) -- (2,-0.5) ; %% T
\draw (2,2) -- (3,-0.5) ;
\draw (2,0.5) -- (3,2) ;
\draw (2,-0.5) -- (3,1) ;
\draw (3,2) -- (3.5,2) ;
\draw (3,1) -- (3.5,1) ;
\draw (3,-0.5) -- (3.5,-0.5) ;
\draw (3.5,2) -- (4.5,1) ;
\draw (3.5,1) -- (4.5,2) ;
\draw (3.5,-0.5) -- (4.5,-0.5) ;
\draw (4.5,2) -- (5,2) ;
\draw (4.5,1) -- (5,1) ;
\draw (4.5,-0.5) -- (5,-0.5) ;
\draw (5,2) -- (6,0.5) ;
\draw (5,1) -- (6,-0.5) ;
\draw (5,-0.5) -- (6,2) ;
\draw (6,2) -- (7,2) ;
\draw (6,0.5) -- (8,0.5) ;
\draw (6,-0.5) -- (8,-0.5) ;
\draw (7,2) ellipse (0.5cm and 0.5cm);
\draw[fill] (7,2) circle [radius=0.025];
\node[below] at (7,2) {*};
\draw (8,0) ellipse (0.5cm and 1cm);
\draw[fill] (8,0.5) circle [radius=0.025];
\node[below] at (8,0.5) {F};
\draw[fill] (8,-0.5) circle [radius=0.025];
\node[below] at (8,-0.5) {T};
\end{tikzpicture}
\end{center}
\caption{\label{fig:not}Graphical representation of {\small\AgdaFunction{notβ}}}
\end{figure}
The programs are all of the same type but this is clearly not a
sufficient condition for ``equivalence.'' Thinking extensionally,
i.e., by looking at all possible input-output pairs, it is easy to
verify that the six programs split into two classes: one consisting of
the first three programs which are all equivalent to the identity
function and the other consisting of the remaining three programs
which all equivalent to boolean negation. In the context of $\Pi$, we
can provide \emph{evidence} (i.e., a reversible program of type
$\isotwo$ that manipulates lower level reversible programs of type
$\iso$ ) that can constructively identify programs in each equivalence
class. We show such a level-2 program proving that
{\small\AgdaFunction{notβ}} is equivalent to
{\small\AgdaFunction{not}}. For illustration, the program for
{\small\AgdaFunction{notβ}} is depicted in Fig.~\ref{fig:not}. We
encourage the reader to map the steps below to manipulations on the
diagram that would incrementally simplify it:
{\small
\[\def\arraystretch{1.2}\begin{array}{rcll}
\AgdaFunction{notOpt} &:& \AgdaFunction{notβ} \isotwo \AgdaFunction{not} \\
\AgdaFunction{notOpt} &=&
\AgdaFunction{unitiβ} \odot_1 (\AgdaFunction{swapβ} \odot_1
((\AgdaFunction{not} \otimes \AgdaFunction{id}) \odot_1
(\AgdaFunction{swapβ} \odot_1 \AgdaFunction{uniteβ})))
& \quad\byisotwo{\AgdaFunction{id} \boxdot \AgdaFunction{assocLeft}} \\
&& \AgdaFunction{unitiβ} \odot_1 (\AgdaFunction{swapβ} \odot_1
(\AgdaFunction{not} \otimes \AgdaFunction{id})) \odot_1
(\AgdaFunction{swapβ} \odot_1 \AgdaFunction{uniteβ})
& \quad\byisotwo{\AgdaFunction{id} \boxdot (\AgdaFunction{swapLeft}
\boxdot \AgdaFunction{id})} \\
&& \AgdaFunction{unitiβ} \odot_1 ((\AgdaFunction{id} \otimes \AgdaFunction{not})
\odot_1 \AgdaFunction{swapβ}) \odot_1
(\AgdaFunction{swapβ} \odot_1 \AgdaFunction{uniteβ})
& \quad\byisotwo{\AgdaFunction{id} \boxdot \AgdaFunction{assocRight}} \\
&& \AgdaFunction{unitiβ} \odot_1 ((\AgdaFunction{id} \otimes \AgdaFunction{not})
\odot_1 (\AgdaFunction{swapβ} \odot_1
(\AgdaFunction{swapβ} \odot_1 \AgdaFunction{uniteβ})))
& \quad\byisotwo{\AgdaFunction{id} \boxdot (\AgdaFunction{id}
\boxdot \AgdaFunction{assocLeft})} \\
&& \AgdaFunction{unitiβ} \odot_1 ((\AgdaFunction{id} \otimes \AgdaFunction{not})
\odot_1 ((\AgdaFunction{swapβ} \odot_1
\AgdaFunction{swapβ}) \odot_1 \AgdaFunction{uniteβ}))
& \quad\byisotwo{\AgdaFunction{id} \boxdot (\AgdaFunction{id}
\boxdot (\AgdaFunction{leftInv} \boxdot \AgdaFunction{id}))} \\
&& \AgdaFunction{unitiβ} \odot_1 ((\AgdaFunction{id} \otimes \AgdaFunction{not})
\odot_1 (\AgdaFunction{id} \odot_1 \AgdaFunction{uniteβ}))
& \quad\byisotwo{\AgdaFunction{id} \boxdot (\AgdaFunction{id}
\boxdot \AgdaFunction{idLeft})} \\
&& \AgdaFunction{unitiβ} \odot_1 ((\AgdaFunction{id} \otimes \AgdaFunction{not})
\odot_1 \AgdaFunction{uniteβ})
& \quad\byisotwo{\AgdaFunction{assocLeft}} \\
&& (\AgdaFunction{unitiβ} \odot_1 (\AgdaFunction{id} \otimes \AgdaFunction{not}))
\odot_1 \AgdaFunction{uniteβ}
& \quad\byisotwo{\AgdaFunction{unitiLeft} \boxdot \AgdaFunction{id}} \\
&& (\AgdaFunction{not} \odot_1 \AgdaFunction{unitiβ}) \odot_1 \AgdaFunction{uniteβ}
& \quad\byisotwo{\AgdaFunction{assocRight}} \\
&& \AgdaFunction{not} \odot_1 (\AgdaFunction{unitiβ} \odot_1 \AgdaFunction{uniteβ})
& \quad\byisotwo{\AgdaFunction{id} \boxdot \AgdaFunction{leftInv}} \\
&& \AgdaFunction{not} \odot_1 \AgdaFunction{id}
& \quad\byisotwo{\AgdaFunction{idRight}} \\
&& \AgdaFunction{not}
\end{array}\]}
\noindent It is worthwhile mentioning that the above derivation could also be
drawn as one (large!) commutative diagram in an appropriate category, with each
$\byisotwo{-}$ as a $2$-arrow (and representing a natural isomorphism). See
Shulman's draft book~\cite{shulman} for that interpretation.
%%%%%
\subsection{A Small Reversible Language of Booleans: \PiTwo}{\label{sec:pi2}}
Having illustrated the general flavor of the $\Pi$ family of
languages, we present in full detail an Agda-based formalization of a
small $\Pi$-based language which we will use to establish the
connection to an explicit univalent universe. The language is the
restriction of $\Pi$ to the case of just one type $\mathbb{2}$:
%% \[\def\arraystretch{0.8}\begin{array}{l@{\quad}rclrl}
%% (\textit{Types}) & \tau &::=& \bt \\
%% \\
%% (\textit{Terms}) & v &::=& \fc &:& \bt \\
%% && \alt & \tc &:& \bt \\
%% \\
%% (\textit{1-combinators}) & c &::=& \id &:& \tau \iso \tau \\
%% && \alt & \swap &:& \bt \iso \bt \\
%% && \alt & ! &:& (\tau_1 \iso \tau_2) \to (\tau_2 \iso \tau_1) \\
%% && \alt & \odot_1 &:& (\tau_1 \iso \tau_2) \to (\tau_2 \iso \tau_3) \to (\tau_1 \iso \tau_3) \\
%% \\
%% (\textit{2-combinators}) & \alpha &::=& \id &:& c \isotwo c \\
%% && \alt & \idlc &:& \compc{\id}{c} \isotwo c \\
%% && \alt & \idrc &:& \compc{c}{\id} \isotwo c \\
%% && \alt & \invl &:& \compc{c\;}{\;\invc{c}} \isotwo \id \\
%% && \alt & \invr &:& \compc{\invc{c}}{c} \isotwo \id \\
%% && \alt & \rho &:& \swap \circ \swap \isotwo \id \\
%% && \alt & \assocc &:&
%% \compc{(\compc{c_1}{c_2})}{c_3} \isotwo \compc{c_1}{(\compc{c_2}{c_3})} \\
%% && \alt & \boxdot &:& (c_1 \isotwo c_1') \to (c_2 \isotwo c_2') \to
%% (\compc{c_1}{c_2} \isotwo \compc{c_1'}{c_2'}) \\
%% && \alt & !! &:& (c_1 \isotwo c_2) \to (c_2 \isotwo c_1) \\
%% && \alt & \bullet &:& (c_1 \isotwo c_2) \to (c_2 \isotwo c_3) \to (c_1 \isotwo c_3)
%% \end{array}\]
\begin{code}
data π : π° where
0β 1β : π
\end{code}
The syntax of \PiTwo\ is given by the following four Agda
definitions. The first definition~{\small\AgdaFunction{Ξ β}} introduces
the set of types of the language: this set contains
just~{\small\AgdaInductiveConstructor{`π}} which is a name for the
type of booleans $\mathbb{2}$. The next three definitions introduce
the programs (combinators) in the language stratified by levels. The
level-1 programs of type $\iso$ map between types; the level-2
programs of type $\isotwo$ map between level-1 programs; and the
level-3 programs of type $\isothree$ map between level-2 programs:
\AgdaHide{
\begin{code}
infix 3 _β·β_ _β·β_ _β·β_
infix 5 !β_ !β_
infix 4 _ββ_ _ββ_
\end{code}
}
\begin{code}
data Ξ β : π° where
`π : Ξ β
---------------
data _β·β_ : (A B : Ξ β) β π° where
`id : β {A} β A β·β A
`not : `π β·β `π
!β_ : β {A B} β (A β·β B) β (B β·β A)
_ββ_ : β {A B C} β (A β·β B) β (B β·β C) β (A β·β C)
---------------
data _β·β_ : β {A B} (p q : A β·β B) β π° where
`idβ : β {A B} {p : A β·β B} β p β·β p
!β_ : β {A B} {p q : A β·β B} β (p β·β q) β (q β·β p)
_ββ_ : β {A B} {p q r : A β·β B} β (p β·β q) β (q β·β r) β (p β·β r)
`idl : β {A B} (p : A β·β B) β `id ββ p β·β p
`idr : β {A B} (p : A β·β B) β p ββ `id β·β p
`assoc : β {A B C D} (p : A β·β B) (q : B β·β C) (r : C β·β D)
β (p ββ q) ββ r β·β p ββ (q ββ r)
_β‘β_ : β {A B C} {p q : A β·β B} {r s : B β·β C}
β (p β·β q) β (r β·β s) β (p ββ r) β·β (q ββ s)
`! : β {A B} {p q : A β·β B} β (p β·β q) β (!β p β·β !β q)
`!l : β {A B} (p : A β·β B) β (p ββ !β p β·β `id)
`!r : β {A B} (p : B β·β A) β (!β p ββ p β·β `id)
`!id : β {A} β !β `id {A} β·β `id {A}
`!not : !β `not β·β `not
`!βΎ : β {A B C} {p : A β·β B} {q : B β·β C}
β !β (p ββ q) β·β (!β q) ββ (!β p)
`!! : β {A B} {p : A β·β B} β !β (!β p) β·β p
---------------
data _β·β_ {A B} {p q : A β·β B} (u v : p β·β q) : π° where
`trunc : u β·β v
\end{code}
% \jacques{The text below doesn't make sense anymore as the
% ``syntactic categories'' were named in the above
% commented out array, but have different names in the Agda
% code.}
In the previous presentations of
$\Pi$~\cite{rc2011,James:2012:IE:2103656.2103667,Carette2016}, the level-3
programs, consisting of just one trivial program
{\small\AgdaInductiveConstructor{`trunc}}, were not made explicit. The much
larger level-1 and level-2 programs of the full $\Pi$
language~\cite{Carette2016} have been specialized to our small language. For the
level-1 constructors, denoting reversible programs, type isomorphisms,
permutations between finite sets, or equivalences depending on one's favorite
interpretation, we have two canonical programs
{\small\AgdaInductiveConstructor{`id}} and
{\small\AgdaInductiveConstructor{`not}} closed under inverses
{\small\AgdaInductiveConstructor{!β}} and sequential
composition~{\small\AgdaInductiveConstructor{ββ}}. For level-2 constructors,
denoting reversible program transformations, coherence conditions on type
isomorphisms, equivalences between permutations, or program optimizations
depending on one's favorite interpretation, we have the following groups: (i)
the first group contains the identity, inverses, and sequential composition;
(ii) the second group establishes the coherence laws for level-1 sequential
composition (e.g, it is associative); and (iii) finally the third group includes
general rules for inversions of level-1 constructors.
Each of the level-2 combinators of type $p \isotwo q$ is easily seen
to establish an equivalence between level-1 programs $p$ and $q$ (as
shown in previous work~\cite{Carette2016} and in
Sec.~\ref{sec:correspondence}). For example, composition of negation
is equivalent to the identity:
\begin{code}
notββnotβ·βid : `not ββ `not β·β `id
notββnotβ·βid = ((!β `!not) β‘β `idβ) ββ (`!r `not)
\end{code}
What is particularly interesting, however, is that the collection of
level-2 combinators above is \emph{complete} in the sense that any
equivalence between level-1 programs $p$ and $q$ can be proved using
the level-2 combinators. Formally we have two canonical level-1
programs {\small\AgdaInductiveConstructor{`id}} and
{\small\AgdaInductiveConstructor{`not}} and for any level-1 program
${\small p}$, we have evidence that either
${\small p \isotwo \AgdaInductiveConstructor{`id}}$ or
${\small p \isotwo \AgdaInductiveConstructor{`not}}$.
To prove this, we introduce a type which encodes the knowledge of
which level-1 programs are canonical. The type {\small\AgdaDatatype{Which}}
names the subset of {\small\AgdaDatatype{β·β}} which are canonical forms:
\begin{code}
data Which : π° where
ID NOT : Which
refine : (w : Which) β `π β·β `π
refine ID = `id
refine NOT = `not
\end{code}
This enables us to compute for any 2-combinator $c$ (the name of) its canonical
form, as well as a proof that $c$ is equivalent to its canonical form:
\begin{code}
canonical : (c : `π β·β `π) β Ξ£[ c' βΆ Which ] (c β·β refine c')
canonical `id = ID , `idβ
canonical `not = NOT , `idβ
canonical (!β c) with canonical c
... | ID , cβ·βid = ID , (`! cβ·βid ββ `!id)
... | NOT , cβ·βnot = NOT , (`! cβ·βnot ββ `!not)
canonical (_ββ_ {_} {`π} cβ cβ) with canonical cβ | canonical cβ
... | ID , cββ·βid | ID , cββ·βid = ID , ((cββ·βid β‘β cββ·βid) ββ `idl `id)
... | ID , cββ·βid | NOT , cββ·βnot = NOT , ((cββ·βid β‘β cββ·βnot) ββ `idl `not)
... | NOT , cββ·βnot | ID , cββ·βid = NOT , ((cββ·βnot β‘β cββ·βid) ββ `idr `not)
... | NOT , cββ·βnot | NOT , cββ·βnot = ID , ((cββ·βnot β‘β cββ·βnot) ββ notββnotβ·βid)
\end{code}
It is worthwhile to note that the proof of
{\small\AgdaFunction{canonical}} does not use all the level-2
combinators. The larger set of 2-combinators is however useful to
establish a more direct connection with the model presented in the
next sections.
% \begin{lemma}[Canonical Forms]
% Given a 1-combinator $c : \tau \iso \tau$, we either have a
% 2-combinator of type $c \isotwo \AgdaFunction{`id}$ or a 2-combinator of type
% $c \isotwo \AgdaFunction{`not}$. In other words, every 1-combinator has a canonical
% representation as either $\AgdaFunction{`id}$ or $\AgdaFunction{`not}$ and the set of 2-combinators is rich
% enough to normalize $c$ to its canonical representation.
% \end{lemma}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\section{HoTT Background}
\label{sec:univalent}
We work in intensional type theory with one univalent universe
{\small\AgdaPrimitiveType{π°}} closed under propositional truncation. The rest
of this section is devoted to explaining what that means. We follow
the terminology used in the HoTT book~\cite{hottbook}. For brevity,
we will often just give type signatures and elide the term. The details
can be found in the accompanying code at
{\small\url{https://git.io/v7wtW}}.
\subsection{Equivalences}
\label{sec:eq}
Given types {\small\AgdaBound{A}} and {\small\AgdaBound{B}}, a function
{\small\AgdaBound{f}~\AgdaSymbol{:}~\AgdaBound{A}~\AgdaSymbol{β}~\AgdaBound{B}}
is a quasi-inverse, if there is another function
{\small\AgdaBound{g}~\AgdaSymbol{:}~\AgdaBound{B}~\AgdaSymbol{β}~\AgdaBound{A}}
that acts as both a left and right inverse to {\small\AgdaBound{f}}:
\begin{code}
is-qinv : {A B : π°} β (f : A β B) β π°
is-qinv {A} {B} f = Ξ£[ g βΆ (B β A) ] (g β f βΌ id Γ f β g βΌ id)
\end{code}
% \VC{Maybe we can split the explanation of contractible and propositions and move
% it to 3.1?}
In general, for a given ${\small\AgdaBound{f}}$, there could be several
unequal inhabitants of the type
${\small\AgdaFunction{is-qinv}~\AgdaBound{f}}$. As Ch.~4 of the HoTT
book~\cite{hottbook} details, this is problematic in the
proof-relevant setting of HoTT. To ensure that a function
${\small\AgdaBound{f}}$ can be an equivalence in at most one way, an
additional coherence condition is added to quasi-inverses to define
\emph{half adjoint equivalences}:
\begin{code}
is-hae : {A B : π°} β (f : A β B) β π°
is-hae {A} {B} f = Ξ£[ g βΆ (B β A) ] Ξ£[ Ξ· βΆ g β f βΌ id ] Ξ£[ Ξ΅ βΆ f β g βΌ id ] (ap f β Ξ· βΌ Ξ΅ β f)
qinv-is-hae : {A B : π°} {f : A β B} β is-qinv f β is-hae f
\end{code}
\AgdaHide{
\begin{code}
qinv-is-hae = {!!}
\end{code}
}
Using this latter notion, we can define a well-behaved notion of
equivalences between two types:
\begin{code}
is-equiv = is-hae
_β_ : (A B : π°) β π°
A β B = Ξ£[ f βΆ (A β B) ] (is-equiv f)
\end{code}
It is straightforward to lift paths to equivalences as shown below:
% \jacques{But transport does not occur below at all, not even
% implicitly. In fact, the 4 functions below are so trivial that
% they could be collapsed into 1 without loss of comprehension.
% Compared to how complex a lot of the rest of this is (such as
% the previous sub-section), what's the point of taking so much
% space with this?}
\AgdaHide{
\begin{code}
idh : {A : π°} {P : A β π°} β (f : Ξ [ a βΆ A ] P a) β f βΌ f
idh f a = refl (f a)
\end{code}
}
\begin{code}
ide : (A : π°) β A β A
ide A = id , id , refl , refl , (refl β refl)
transport-equiv : {A : π°} (P : A β π°) β {a b : A} β a == b β P a β P b
transport-equiv P (refl a) = ide (P a)
id-to-equiv : {A B : π°} β A == B β A β B
id-to-equiv = transport-equiv id
\end{code}
Dually, univalence allows us to construct paths from equivalences. We postulate
univalence as an axiom in our Agda library:
\begin{code}
postulate
univalence : (A B : π°) β is-equiv (id-to-equiv {A} {B})
\end{code}
We also give a short form {\small\AgdaFunction{ua}} for getting a path from an
equivalence, and prove some computation rules for it:
\begin{code}
module _ {A B : π°} where
ua : A β B β A == B
ua = prβ (univalence A B)
ua-Ξ² : id-to-equiv β ua βΌ id
ua-Ξ² = prβ (prβ (prβ (univalence A B)))
ua-Ξ²β : transport id β ua βΌ prβ
ua-Ξ²β eqv = transport _ (ua-Ξ² eqv) (ap prβ)
ua-Ξ· : ua β id-to-equiv βΌ id
ua-Ξ· = prβ (prβ (univalence A B))
\end{code}
\subsection{Propositional Truncation}
A type {\small\AgdaBound{A}} is \emph{contractible} (h-level 0 or
(-2)-truncated), if it has a center of contraction, and all other
terms of {\small\AgdaBound{A}} are connected to it by a path:
%% \VC{FIXME: Ξ£ and Ξ are rendered in different colors}
%% \amr{one is a record and one is a function. Ok I guess}
\begin{code}
is-contr : (A : π°) β π°
is-contr A = Ξ£[ a βΆ A ] Ξ [ b βΆ A ] (a == b)
\end{code}
As alluded to in the previous section, equivalences are contractible
(4.2.13 in~\cite{hottbook}):
\begin{code}
is-equiv-is-contr : {A B : π°} {f : A β B} β is-equiv f β is-contr (is-equiv f)
\end{code}
\AgdaHide{
\begin{code}
is-equiv-is-contr = {!!}
\end{code}
}
A type {\small\AgdaBound{A}} is a \emph{proposition} (h-level 1 or
(-1)-truncated) if all pairs of terms of {\small\AgdaBound{A}} are
connected by a path. Such a type can have at most one inhabitant; it is
``contractible if inhabited.'' Finally, a type {\small\AgdaBound{A}} is
a \emph{set} if for any two terms {\small\AgdaBound{a}} and
{\small\AgdaBound{b}} of {\small\AgdaBound{A}}, its type of paths
{\small\AgdaBound{a}~\AgdaFunction{==}~\AgdaBound{b}} is a proposition:
\begin{code}
is-prop : (A : π°) β π°
is-prop A = Ξ [ a βΆ A ] Ξ [ b βΆ A ] (a == b)
is-set : (A : π°) β π°
is-set A = Ξ [ a βΆ A ] Ξ [ b βΆ A ] is-prop (a == b)
\end{code}
Any type can be truncated to a proposition by freely adding
paths. This is the propositional truncation (or (-1)-truncation) which
can be expressed as a higher inductive type (HIT). The type
constructor {\small\AgdaInductiveConstructor{β₯\_β₯}} takes a type
{\small\AgdaBound{A}} as a parameter; the point constructor
{\small\AgdaInductiveConstructor{β£\_β£}} coerces terms of type
{\small\AgdaBound{A}} to terms in the truncation; and the path
constructor {\small\AgdaInductiveConstructor{ident}} identifies any
two points in the truncation, making it a proposition. We must do this
as a {\small\AgdaKeyword{postulate}} as Agda does not yet support
HITs:
\begin{code}
postulate
β₯_β₯ : (A : π°) β π°
β£_β£ : {A : π°} β (a : A) β β₯ A β₯
ident : {A : π°} {a b : β₯ A β₯} β a == b
β₯-β₯-is-prop : {A : π°} β is-prop β₯ A β₯
β₯-β₯-is-prop _ _ = ident
\end{code}
This makes
{\small\AgdaInductiveConstructor{β₯}\AgdaBound{A}\AgdaInductiveConstructor{β₯}}
the ``free'' proposition on any type {\small\AgdaBound{A}}. The
recursion principle (below) ensures that we can only eliminate a
propositional truncation to a type that is a proposition:
\begin{code}
module _ {A : π°} (P : π°) (f : A β P) (Ο : is-prop P) where
postulate
rec-β₯-β₯ : β₯ A β₯ β P
rec-β₯-β₯-Ξ² : Ξ [ a βΆ A ] (rec-β₯-β₯ β£ a β£ == f a)
\end{code}
\begin{figure}
\begin{tabular}{c@{\qquad\qquad}c}
\begin{tikzpicture}[scale=0.7,every node/.style={scale=0.7}]]
\draw (0,-5) ellipse (2cm and 0.8cm);
\node[below] at (0,-6) {Base Space $A$};
\draw[fill] (-1,-5) circle [radius=0.025];
\node[below] at (-1,-5) {$x$};
\draw[fill] (1,-5) circle [radius=0.025];
\node[below] at (1,-5) {$y$};
\draw (-1,-2) ellipse (0.5cm and 2cm);
\node[left] at (-1.5,-2) {Fiber $P(x)$};
\draw (1,-2) ellipse (0.5cm and 2cm);
\node[right] at (1.5,-2) {Fiber $P(y)$};
\end{tikzpicture}
&
\begin{tikzpicture}[scale=0.7,every node/.style={scale=0.7}]]
\draw (0,-5) ellipse (2cm and 0.8cm);
\node[below] at (0,-6) {Base Space $A$};
\draw[fill] (-1,-5) circle [radius=0.025];
\node[below] at (-1,-5) {$x$};
\draw[fill] (1,-5) circle [radius=0.025];
\node[below] at (1,-5) {$y$};
\draw (-1.3,-2) ellipse (0.5cm and 2cm);
\node[left] at (-1.8,-2) {Fiber $P(x)$};
\draw (1.3,-2) ellipse (0.5cm and 2cm);
\node[right] at (1.8,-2) {Fiber $P(y)$};
\draw[below,cyan,thick] (-1,-5) -- (1,-5);
\node[below,cyan,thick] at (0,-5) {$==$};
\draw[->,red,thick] (-0.8,-1.7) to [out=45, in=135] (0.8,-1.7);
\draw[->,red,thick] (0.8,-2.3) to [out=-135, in=-45] (-0.8,-2.3);
\node[red,thick] at (0,-2) {$\simeq$};
\end{tikzpicture}
\end{tabular}
\caption{\label{fig:fib}(left) Type family $P : A \rightarrow \mathcal{U}$ as a
fibration with total space $\Sigma_{(x:A)} P(x)$;\newline
(right) a path $x == y$
in the base space induces an equivalence between the spaces (fibers)
$P(x)$ and $P(y)$}
\end{figure}
\subsection{Type Families are Fibrations}
As illustrated in Fig.~\ref{fig:fib}, a type family
{\small\AgdaBound{P}} over a type~{\small\AgdaBound{A}} is a fibration
with base space~{\small\AgdaBound{A}}, with every