-
Notifications
You must be signed in to change notification settings - Fork 13
/
agda.lagda.tex
2963 lines (2642 loc) · 111 KB
/
agda.lagda.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
\documentclass[a4paper,UKenglish]{tufte-handout}
\usepackage[utf8]{inputenc}
\usepackage{microtype}
\DisableLigatures{encoding=*,family=tt*}
\usepackage{mathtools}
\usepackage{amsmath}
\usepackage{mathpartir}
\usepackage{agda}
\usepackage{geometry}
\usepackage{hyperref}
\hypersetup{colorlinks=true, linkcolor=black, citecolor=black, filecolor=black, urlcolor=black}
\usepackage[parfill]{parskip}
\usepackage{color,colortbl,xcolor}
\usepackage{booktabs}
\usepackage{amsthm}
\usepackage{tikz}
\usetikzlibrary{positioning}
\newcommand{\hrefu}[2]{\href{#1}{\nolinkurl{#2}}}
\theoremstyle{definition}
\newtheorem{exercise}{Exercise}[section]
\clubpenalty=10000
\widowpenalty=10000
\displaywidowpenalty=10000
\hfuzz=1000pt
\setcounter{secnumdepth}{1}
\usepackage{newunicodechar}
\newunicodechar{→}{\ensuremath{\rightarrow}}
\newunicodechar{←}{\ensuremath{\leftarrow}}
\newunicodechar{×}{\ensuremath{\times}}
\newunicodechar{λ}{\ensuremath{\lambda}}
\newunicodechar{∀}{\ensuremath{\forall}}
\newunicodechar{Π}{\ensuremath{\Pi}}
\newunicodechar{Σ}{\ensuremath{\Sigma}}
\newunicodechar{≡}{\ensuremath{\equiv}}
\newunicodechar{≅}{\ensuremath{\cong}}
\newunicodechar{≐}{\ensuremath{\doteq}}
\newunicodechar{∈}{\ensuremath{\in}}
\newunicodechar{∧}{\ensuremath{\land}}
\newunicodechar{∨}{\ensuremath{\lor}}
\newunicodechar{⊤}{\ensuremath{\top}}
\newunicodechar{⊥}{\ensuremath{\bot}}
\newunicodechar{⊔}{\ensuremath{\sqcup}}
\newunicodechar{∷}{\ensuremath{{::}}}
\newunicodechar{ℓ}{\ensuremath{\ell}}
\newunicodechar{₀}{\ensuremath{{_0}}}
\newunicodechar{₁}{\ensuremath{{_1}}}
\newunicodechar{₂}{\ensuremath{{_2}}}
\newunicodechar{₃}{\ensuremath{{_3}}}
\newunicodechar{₄}{\ensuremath{{_4}}}
\newunicodechar{₅}{\ensuremath{{_5}}}
\newunicodechar{₆}{\ensuremath{{_6}}}
\newunicodechar{₇}{\ensuremath{{_7}}}
\newunicodechar{₈}{\ensuremath{{_8}}}
\newunicodechar{₉}{\ensuremath{{_9}}}
\newunicodechar{⟨}{\ensuremath{{\langle}}}
\newunicodechar{⟩}{\ensuremath{{\rangle}}}
\newunicodechar{̧}{\c}
\newunicodechar{∘}{\ensuremath{\circ}}
\newcommand\var[1]{\mathit{#1}}
\newcommand\prim[1]{{\AgdaPrimitive{#1}}}
\newcommand\ty[1]{{{\prim{Set}}_{#1}}}
\newcommand\fun[1]{{\AgdaFunction{#1}}}
\newcommand\data[1]{{\AgdaFunction{#1}}}
\newcommand\con[1]{{\AgdaInductiveConstructor{#1}}}
\newcommand\field[1]{{\AgdaField{#1}}}
\newcommand\keyw[1]{{\AgdaKeyword{#1}}}
\newcommand\lit[1]{{\AgdaNumber{#1}}}
\newcommand\level{\fun{Level}}
\newcommand\ite[3]{\fun{if}\ #1\ \fun{then}\ #2\ \fun{else}\ #3}
\newcommand\Nat{\data{Nat}}
\newcommand\zero{\con{zero}}
\newcommand\suc{\con{suc}}
\newcommand\Bool{\data{Bool}}
\newcommand\true{\con{true}}
\newcommand\false{\con{false}}
\newcommand\just{\con{just}}
\newcommand\nothing{\con{nothing}}
\renewcommand\left{\con{left}}
\renewcommand\right{\con{right}}
\newcommand\List{\data{List}}
\renewcommand\Vec{\data{Vec}}
\newcommand\nil{\con{[]}}
\newcommand\cons{\con{::}}
\newcommand\Fin{\data{Fin}}
\renewcommand\prod{\data{×}}
\newcommand\sigmatype{\data{Σ}}
\newcommand\toptype{\data{⊤}}
\newcommand\bottomtype{\data{⊥}}
\newcommand\Id{\data{≡}}
\newcommand\refl{\con{refl}}
\title{Programming and Proving in Agda}
\author{Jesper Cockx}
\date{Version of \today}
\begin{document}
\begin{code}[hide]
{-# OPTIONS --allow-unsolved-metas #-}
\end{code}
\maketitle
\begin{abstract}
Agda is both a strongly typed functional programming language with
support for first-class \emph{dependent types} and a \emph{proof
assistant} based on the Curry-Howard correspondence between
propositions and types. The goal of these lecture notes is to introduce both
these unique aspects of Agda to a general audience of functional
programmers. It starts from basic knowledge of Haskell as taught in
Hutton's book \emph{Programming in Haskell}, and builds up to
using equational reasoning to formally prove correctness of
functional programs.
\end{abstract}
\tableofcontents
\clearpage
\section{An introduction to Agda for Haskell programmers}
Most programmers think of a type system as a set of rules that
together prevent a class of basic runtime errors, such as using a
string where the program expects an integer. This is indeed why type
systems were first introduced to programming languages: to prevent
program crashes that would follow from interpreting data in memory
incorrectly.\footnote{For example, a type system can prevent the
floating point number $1.0$ from being interpreted as a memory
address.} However, since their invention, type systems have evolved
to include a much broader range of applications:
\begin{itemize}
\item By making use of type information, an IDE can help the
programmer during the programming by providing type information and
suggestions and by generating and modifying code based on the type
information. For example, the IDE can use types to generate all
possible cases in a case expression.
\item A type can express precise invariants of data in a program, such
as the length of a list or the lower and upper bounds of a search
tree. These expressive types that can depend on runtime inputs are
known as \emph{dependent types}.
\item Types can even be used to express mathematical properties and
proofs of these properties, which can be checked automatically by the
type checker. This usage of a type system as a logic is based on a
deep and fundamental result known as the \emph{Curry-Howard
correspondence}.
\end{itemize}
While strongly typed languages such as Java or Haskell have type
systems that are quite expressive, due to various reasons it is hard
to fully appreciate the three above points from their
perspective. In these lecture notes, we will study Agda, a functional language that
is similar to Haskell but is a bit more experimental and has an even
more expressive type system with full support for dependent types.
On the surface level, Agda code looks quite similar to Haskell code,
with some small syntactic differences. However, beneath the hood are a
number of notable differences:
\marginnote{%
\paragraph{Historical note.} Agda's type system is based on
\emph{dependent type theory}, a formal language invented by the
Swedish philosopher Per Martin-L\"of. His original motivation was to
provide a new foundation for \emph{constructive mathematics}, a kind
of mathematics where each proof of existence contains an algorithm to
actually construct the object that is proven to exist. For example, a
constructive proof of ``there exists a prime number greater than
1000'' provides an algorithm to actually produce such a number. Later
on, it was discovered that Martin-L\"of's type theory is also well
suited to implement computer proof assistants (such as the Coq system)
and programming languages with built-in support for verification (such
as Agda).
}
\begin{itemize}
\item Types in Agda are \emph{first-class values}: basic types such as
$\Nat$ and $\Bool$ are themselves values of another type called
$\ty{}$. Values of type $\ty{}$ can be passed around as arguments
and returned just as other values.
\item All functions in Agda are \emph{total}: where evaluating a
function call in Haskell could lead to a runtime error or loop
forever, evaluating a function call in Agda is guaranteed to always
return a value of the correct type in finite time.
\item Agda has support for \emph{dependent function types} where the
type of the output can be different depending on the runtime value
of the input. This allows us to assign a precise type to functions
that are impossible to type correctly in many other languages, such
as $\fun{printf}$.
\item Agda also has types that correspond to (proofs of) \emph{logical
propositions}. Using these types, Agda can also be used as a
\emph{proof assistant} for writing and checking mathematical proofs.
\end{itemize}
The goal of these lecture notes is \emph{not} to provide a full guide to using
Agda as a full-featured programming language. Instead, we use Agda as a vehicle
to study the basic building blocks that make up a dependently typed functional
programming language. Most of the types and functions we define --- as well as
much more --- can be found in Agda's standard library, which you can get from
\hrefu{https://github.com/agda/agda-stdlib}{github.com/agda/agda-stdlib}. In
these notes, we will not make use of the standard library and instead define
everything from the ground up. When using Agda for real, it is of course
much easier to get these definitions from the library instead!
\subsection{Installing Agda}
To follow the rest of these notes, it is recommended that you use Agda
version 2.6.0 or later. There are several ways to install Agda.
\begin{description}
\item[Agda Language Server for VS Code.] The easiest way to install
Agda is to first install Visual Studio
Code\footnote{\hrefu{https://code.visualstudio.com/}{code.visualstudio.com}}
and the Agda Mode
plugin\footnote{\hrefu{https://github.com/banacorn/agda-mode-vscode}{github.com/banacorn/agda-mode-vscode}}
and then enable `agdaMode.connection.agdaLanguageServer` in the
settings. This will automatically download a suitable version of
Agda the first time you load an Agda file.
\item[Ubuntu package.] On Ubuntu Linux and similar systems
(including
WSL\footnote{\hrefu{https://docs.microsoft.com/en-us/windows/wsl/install-win10}{docs.microsoft.com/en-us/windows/wsl/install-win10}}
on Windows) you can install a binary release of Agda by running
`\texttt{sudo apt install agda}` (plus `sudo apt install elpa-agda2-mode` if you use Emacs).
\item[Installation from source using Cabal or Stack.] You can also
install Agda from source using Cabal or Stack.\footnote{These
tools can be installed using GHCup, which you can find at
\hrefu{https://www.haskell.org/ghcup/}{haskell.org/ghcup}.} You
can compile and install Agda by running \texttt{cabal install
Agda} if using Cabal, or \texttt{stack install Agda} if using
Stack. This step will take a long time and a lot of memory to
complete, and use up 4-5 GB of disk space for a fresh install.
\end{description}
To write and edit Agda code, we recommend Visual Studio Code with the
\texttt{agda-mode} extension.\footnote{You can get Visual Studio Code
from \hrefu{https://code.visualstudio.com/}{code.visualstudio.com}. To install an extension,
click the Extensions button on the left, enter the name of the
extension, and click `install'.} Other IDEs with support for Agda are
Emacs and Atom.
You can test to see if you've installed Agda correctly by creating a file
called \texttt{hello.agda} with these lines:
\begin{code}[number]
data Greeting : Set where
hello : Greeting
greet : Greeting
greet = hello
\end{code}
Open this file in VS Code and press the key combination
\texttt{Ctrl+c} followed by \texttt{Ctrl+l} (for ``load file''). You
should see a new frame titled Agda with the message \texttt{*All
Done*}, and the code should be highlighted.\footnote{In this
introduction to Agda we will only use the interactive mode of Agda,
which acts as a type checker and interpreter similar to \texttt{ghci}
for Haskell. Agda also supports several backends for compilation,
including a GHC backend and a JavaScript backend. A full ``Hello,
world'' example for creating an executable from your Agda code can be
found at
\hrefu{https://agda.readthedocs.io/en/v2.6.3/getting-started/hello-world.html}{agda.readthedocs.io/en/v2.6.3/getting-started/hello-world.html}.}
Once you have loaded an Agda file, there is a number of other commands that
can be used to query the typechecker. Here are two that are used very often:
\begin{description}
\item[Deduce type (\texttt{Ctrl+c Ctrl+d})] This command will ask you
for an expression, for which it will then try to infer the type. For
example, running this command and entering \texttt{hello} will
return the inferred type \texttt{Greeting}.
\item[Normalize expression (\texttt{Ctrl+c Ctrl+n})] This command will ask you
for an expression, which it will evaluate as far as possible. For
example, running this command and entering \texttt{greet} will
return the fully evaluated term \texttt{hello}.
\end{description}
Since there is no syntactic difference between values, functions, and types in
Agda, it can be difficult at first to determine what kind of expression you are
dealing with. If you run into such a situation, try first to predict its type
and normal form, and then use the commands above to test your prediction.
\subsection{Syntactic differences with Haskell}
As we noted before, the syntax of Agda is in many respects similar to
that of Haskell. Here we list the most important differences:
\begin{description}
\item[Typing] Typing is denoted by a single colon in Agda. For example, instead
of writing \texttt{b ::~Bool} as in Haskell, in Agda we write $\fun{b} : \Bool$
to indicate that \fun{b} is a boolean.
\item[Unicode] Agda allows optional use of unicode symbols in
code. For example, we can write $\Bool \to \Bool$ instead of
\texttt{Bool -> Bool} and $\lambda\ x \to x$ instead of
\texttt{\textbackslash x -> x}. It is also allowed to use unicode
symbols in names of definitions and variables. For example, we can
define a function that is named $\surd$.\footnote[][-2cm]{Many
unicode characters can be entered easily using LaTeX syntax when
using the Agda mode for VS Code. For example, when you type
\texttt{\textbackslash{}to} it will be replaced by $\to$, and
\texttt{\textbackslash{}lambda} is replaced by $\lambda$. A full
list of the unicode characters used in these lecture notes and how
to input them can be found in the appendix.}
\item[Naming] In Agda there is no syntactic difference between an
expression and a type. As a consequence, there are no restrictions
on what names have to start with a small letter or a capital
letter. In addition, almost all ascii and unicode
characters\footnote{The exceptions are the symbols
\texttt{.;\{\}()\@"}.} can be used as part of a name. As a
convention, names of functions, constructors, and variables in Agda
code usually start with a small letter, while names of both type
constructors and type variables usually start with a capital
letter. While this naming convention is not enforced by the
language, we will keep to it in these notes.
\item[Operators] To refer to the name of an operator such as $+$ in isolation,
Agda uses underscores (as opposed to parentheses in Haskell). For example, we
have $\fun{\_+\_} : \Nat \to \Nat \to \Nat$.
\marginnote[-1cm]{%
\paragraph{Warning.} Agda will interpret
all names with underscores as operators, so the use of underscores in
non-operator names is strongly discouraged.
}
\item[Whitespace] Due to the liberal naming rules, Agda requires the use of
spaces before and after each operator. For example, Agda requires you to write
\texttt{1\ +\ 1} instead of \texttt{1+1}. In fact, \texttt{1+1} is a valid name
for a function or variable!
\item[Lists] Unlike Haskell, Agda does not assign a special role to lists
compared to other data structures. In particular, there is no special syntax
for list literals or list comprehensions in Agda. Instead, the type
$\data{List}\ A$ is simply a datatype defined with two constructors $\nil$
and $\cons$. The Haskell list \texttt{[1,2,3]} can then be written in
Agda as $\lit{1}\ \cons\ \lit{2}\ \cons\ \lit{3}\ \cons\ \nil$.
\item[Tuples] Similarly, Agda does not have a special built-in type of
tuples. Instead, the type $A\ \data{×}\ B$ is defined as a datatype
with one constructor $\con{\_,\_}$. For example, we have $(\lit{6}\
\con{,}\ \true) : \Nat\ \data{×}\ \Bool$.
%\item[Type classes] Agda does not have type classes as in Haskell. Instead, it
%has a feature known as \emph{instance arguments} that can be used for a similar
%purpose. The use of instance arguments is beyond the scope of these notes.
\end{description}
\subsection{Data types and pattern matching}
Like in Haskell, the core part of any Agda program consists of declarations of
new \emph{data types} and new \emph{function definitions} by pattern
matching on these data types.
Unlike Haskell, there is no automatic import of any modules from the standard
library, so we are free to either load whichever library we want or define
everything from scratch. In this introduction, we will do the latter.
Let's define our first datatype in Agda: the type of (unary) natural numbers:
\begin{code}[number]
data Nat : Set where
zero : Nat
suc : Nat → Nat
\end{code}
\marginnote[-4cm]{%
\paragraph{Natural number literals.} By default, this definition of natural numbers
forces us to write out the numbers as $\zero$, $\suc\ \zero$,
$\suc\ (\suc\ \zero)$, \ldots. However, Agda also has built-in support
for decimal numbers, which we can activate by writing the following
pragma below the definition of $\Nat$:
\begin{code}
{-# BUILTIN NATURAL Nat #-}
\end{code}
Once we have activated this pragma, Agda will interpret the numbers
$\lit{0}$, $\lit{1}$, $\lit{2}$, \ldots using the constructors $\zero$ and $\suc$.
}
The datatype definition consists of a \emph{data signature} $\data{Nat} : \ty{}$ and
two \emph{constructor signatures} $\zero : \Nat$ and $\suc : \Nat \to \Nat$.
We can immediately spot a few differences with the corresponding Haskell
definition \texttt{data Nat = Zero | Suc Nat}:
\begin{itemize}
\item The names of the constructors start with a small letter instead of a
capital letter (see \emph{Naming} above).
\item The definition spells out the full type of each constructor instead of
just the types of their arguments.
\item The definition also assigns a type to the symbol $\data{Nat}$ itself,
namely $\data{Nat} : \ty{}$. The reason is that each defined symbol in Agda
must have a type - including types themselves - and $\ty{}$ is the type of
`simple' types such as $\data{Nat}$.
\end{itemize}
Next, we define addition $\fun{\_+\_}$ on natural numbers by pattern
matching as follows:
\begin{code}[number]
_+_ : Nat → Nat → Nat
zero + y = y
(suc x) + y = suc (x + y)
\end{code}
Just like in Haskell, a definition by pattern matching consists of a \emph{type signature} followed by a list of
\emph{clauses} or equalities. Also like in Haskell, functions can make
\emph{recursive calls} to themselves on the right-hand side of a clause.
\marginnote{
\begin{exercise}
Define the function $\fun{halve} : \Nat → \Nat$ that
computes the result of dividing the given number by 2 (rounded down). Test your
definition by evaluating it for several concrete inputs.
\end{exercise}
}
To test our definition, we first load the file in VS Code
(\texttt{Ctrl+c Ctrl+l}) and then ask Agda to evaluate an expression
by pressing \texttt{Ctrl+c Ctrl+n} (for ``normalize expression''). A
prompt will appear where you can enter the term to be evaluated. For
example, if you enter \texttt{1 + 1} you should get
back the response \texttt{2}.
\marginnote{
\begin{exercise}
Define the function $\fun{\_*\_} : \Nat → \Nat → \Nat$ for multiplication
of two natural numbers.
\end{exercise}
}
\marginnote{
\begin{exercise}
Define the type $\data{Bool}$ with constructors
$\true$ and $\false$, and define the functions for negation
$\fun{not} : \Bool → \Bool$, conjunction $\fun{\_\&\&\_} : \Bool → \Bool → \Bool$,
and disjunction $\fun{\_\textbar\textbar\_} : \Bool → \Bool → \Bool$ by pattern matching.
\end{exercise}
}
\begin{code}[hide]
data Bool : Set where
true : Bool
false : Bool
\end{code}
\subsection{Interactive programming in Agda}
One of the unique features of Agda is its support for
\emph{interactive programming}, which is integrated closely with the
typechecker. To use the interactive mode of Agda, you start by writing
an incomplete definition with one or more \emph{holes}, placeholders
for code you haven't written yet. Holes are written in Agda code as a
question mark \texttt{?} or the special string \texttt{\{!!\}}.
\begin{code}[hide]
module ThrowAway1 where
\end{code}
\begin{code}[number]
not : Bool → Bool
not b = {! !}
\end{code}
Agda can load a file even if it still contains holes. If you load the
file (with \texttt{Ctrl+c Ctrl+l}), Agda will assign a number to the holes and give you
some information about each one:
\begin{verbatim}
?0 : Bool
\end{verbatim}
Once you have loaded a file with holes, there are various ways you can
ask the Agda typechecker to help you through the use of shortcuts:%
\footnote{When you have edited your code in some way and you
want to run one of these commands, always remember to first load the
file using \texttt{Ctrl+c Ctrl+l}.}
\begin{description}
\item[Get goal type and context (\texttt{Ctrl+c Ctrl+,})] This command
will give you the type of the hole the cursor is currently in, as
well as the types of all the variables that are currently in
scope. For example, for the hole above you get:
\begin{verbatim}
Bool
b : Bool
\end{verbatim}
\item[Case (\texttt{Ctrl+c Ctrl+c})] This command will perform a case
split on a variable. For example, if you put the cursor in the hole
in the definition of \fun{not} and press \texttt{Ctrl+c Ctrl+c},
Agda will prompt us for a variable to split on. You can then
enter the name $\var{b}$ of the variable and press \texttt{enter},
giving us the following result:
\begin{code}[hide]
module ThrowAway2 where
\end{code}
\begin{code}[number]
not : Bool → Bool
not true = {! !}
not false = {! !}
\end{code}
Alternatively, you can first enter the name of a variable in
the hole (between the \texttt{\{!} and \texttt{!\}} signs)
and then press \texttt{Ctrl+c Ctrl+c} to split on that variable.
\item[Give (\texttt{Ctrl+c Ctrl+space})] This command allows
you to enter an expression into a hole. For example, if you put
our cursor in the first hole in the definition of \fun{not}
and press \texttt{Ctrl+c Ctrl+space}, Agda will prompt us
for an expression to give. You can then enter $\false$ in
the prompt and press \texttt{enter}. Agda will check that the
expression is of the right type (in this case \data{Bool}) and
then (if typechecking is successful) replace the hole with the given
expression.
\begin{code}[hide]
module ThrowAway3 where
\end{code}%
\begin{code}[number]
not : Bool → Bool
not true = false
not false = {! !}
\end{code}
By doing the same with the term $\true$ in the second hole,
the definition of $\fun{not}$ is completed.
\begin{code}[hide]
not : Bool → Bool
not true = false
not false = true
\end{code}
Alternatively, you can first enter an expression into
the hole and then
press \texttt{Ctrl+c Ctrl+space} to replace the hole with that expression.
% TODO: refine (C-c C-r)
\end{description}
\marginnote{\paragraph{Writing programs interactively.} When starting
out with Agda, it may feel easier to not use the interactive commands
and instead write the program directly. However, once the types of
your program become more complex, it becomes much more difficult to
write down the definition directly and you will need to rely more and
more on these interactive commands. So it is a good idea to get some
experience with these commands by using them as often as possible.}
You can get a full overview of all available commands by pressing
\texttt{Ctrl+Shift+P} to open the command palette in VS Code and then typing
\texttt{Agda}.
\subsection{The $\ty{}$ type and polymorphic functions}
One of the fundamental features of Agda is that types such as
$\data{Nat}$ or $\data{Bool}$ are first-class values that can be
returned and passed around as arguments. The type of $\data{Nat}$ and
$\data{Bool}$ is called $\ty{}$ by Agda. For example, we can define an
alias for $\data{Nat}$ as follows:
\begin{code}[number]
MyNat : Set
MyNat = Nat
\end{code}
This works just like the declaration \texttt{type MyNat = Nat} in
Haskell: the type checker will treat the two types $\data{Nat}$ and
$\fun{MyNat}$ as identical for all intents and purposes.
The type $\ty{}$ is also used to implement polymorphic functions and
datatypes in Agda. For example, we can define the polymorphic identity
function $\fun{id}$ as follows:
\begin{code}[hide]
module ThrowAwayId where
\end{code}
\begin{code}[number]
id : (A : Set) → A → A
id A x = x
\end{code}
The function \fun{id} takes two arguments: a type $A$ of type $\ty{}$
and an element $x$ of type $A$. For example, $\fun{id}\ \Bool\ \true$
has type $\Bool$ and evaluates to $\true$, while
$\fun{id}\ \Nat\ \zero$ has type $\Nat$ and evaluates to $\zero$.
\marginnote[-4cm]{\paragraph{The type of $\ty{}$.} Since all the types we have seen so far have type
$\ty{}$, and $\ty{}$ itself is also a type, you might be wondering
whether $\ty{}$ itself also has type $\ty{}$, i.e.~whether we have
$\ty{} : \ty{}$. The answer is no: there are deep reasons why this is
not allowed in Agda. Concretely, in 1972 the logician Jean-Yves Girard
discovered a paradox in type theory (which is also at the basis of
Agda). If Agda would allow $\ty{} : \ty{}$, it would break logical
soundness of Agda, which is important for using Agda as a theorem
prover (see later). More concretely, with $\ty{} : \ty{}$ it would
be possible to circumvent Agda's termination checker and implement
non-terminating functions. To avoid this paradox and
the problems it causes, Agda introduces another type $\ty{1}$ such
that $\ty{} : \ty{1}$, a type $\ty{2}$ such that $\ty{1} : \ty{2}$, et
cetera.}
Since writing out the type arguments each time becomes boring quickly,
Agda also allows them to be declared \emph{implicit} by using curly
braces $\{\}$:
\begin{code}[number]
id : {A : Set} → A → A
id x = x
\end{code}
With this definition, we can simply write $\fun{id}\ \true$ or
$\fun{id}\ \zero$ and Agda will infer the type automatically.
As another example, \texttt{if/then/else} can simply be defined as a
function in Agda:
\begin{code}[number]
if_then_else_ : {A : Set} → Bool → A → A → A
if true then x else y = x
if false then x else y = y
\end{code}
Note that the underscores $\_$ in the name will make Agda recognize it
as an operator, so we can write terms such as
$\fun{if}\ b\ \allowbreak\fun{then}\ \false\ \allowbreak\fun{else}\ \true$.
Just as we can define polymorphic functions, we can also define
polymorphic datatypes by adding an argument of type $\ty{}$. For
example, the type of lists can be defined as follows:%
\footnote[][-1.5cm]{In order to write expressions such as
$\lit{1}\ \cons\ \lit{2}\ \cons\ \lit{3}\ \cons\ \nil$ (as opposed to
$\lit{1}\ \cons\ (\lit{2}\ \cons\ (\lit{3}\ \cons\ \nil))$), we also need to tell Agda
that $\cons$ is right associative. We can do so as follows:
\begin{code}
infixr 5 _::_
\end{code}
}
\begin{code}[number]
data List (A : Set) : Set where
[] : List A
_::_ : A → List A → List A
\end{code}
Similarly, we can define the type of pairs as a polymorphic
datatype. In Agda, the type of pairs is usually written as $A\ \prod\
B$ in analogy of the notion of the product of two sets in
mathematics.\footnote{To write $\prod$, type
\texttt{\textbackslash{}times}.} It is defined as follows:
\begin{code}[number]
data _×_ (A B : Set) : Set where
_,_ : A → B → A × B
infixr 4 _,_
\end{code}
We can define functions on pairs by pattern matching, for example:
\begin{code}[number]
fst : {A B : Set} → A × B → A
fst (x , y) = x
snd : {A B : Set} → A × B → B
snd (x , y) = y
\end{code}
\marginnote[-2cm]{
\begin{exercise}
Implement the following Agda functions:
\begin{itemize}
\item $\fun{length} : \{ A : \ty{} \} \to \data{List}\ A \to \Nat$
\item $\fun{\_++\_} : \{ A : \ty{} \} \to \data{List}\ A \to \data{List}\ A \to \data{List}\ A$
\item $\fun{map} : \{A\ B : \ty{}\} \to (A \to B) \to \data{List}\ A \to \data{List}\ B$
\end{itemize}
\end{exercise}
}
\begin{code}[hide]
length : {A : Set} → List A → Nat
length [] = 0
length (x :: xs) = suc (length xs)
_++_ : {A : Set} → List A → List A → List A
[] ++ ys = ys
(x :: xs) ++ ys = x :: (xs ++ ys)
map : {A B : Set} → (A → B) → List A → List B
map f [] = []
map f (x :: xs) = f x :: map f xs
\end{code}
\marginnote{
\begin{exercise}
Implement the type $\data{Maybe}\ A$ with two
constructors $\just : A \to \data{Maybe}\ A$ and $\nothing :
\data{Maybe}\ A$. Next, implement the function $\fun{lookup} : \{ A :
\ty{} \} \to \List\ A \to \Nat \to \data{Maybe}\ A$ that returns the
element at the given position in the list.
\end{exercise}
}
\begin{code}[hide]
data Maybe (A : Set) : Set where
just : A → Maybe A
nothing : Maybe A
lookup : {A : Set} → List A → Nat → Maybe A
lookup [] n = nothing
lookup (x :: xs) zero = just x
lookup (x :: xs) (suc n) = lookup xs n
\end{code}
\subsection{Totality checking}
If we call a function in Haskell, we know (thanks to purity) that it will not
perform arbitrary side-effects like doing IO or modifying global variables.
However, there are still a few things that could happen:
\begin{itemize}
\item There could be an error in the program due to an incomplete pattern
match, or because the program contains a call to \texttt{error} or
\texttt{undefined}.
\item The function might not return because it gets stuck in an infinite loop.
\end{itemize}
Since functions in Haskell do not always produce a result, we call Haskell a
\emph{partial language}.
In contrast, Agda is a \emph{total language}, i.e.~Agda functions are
\emph{total functions} in the mathematical sense:
\begin{itemize}
\item There is no \texttt{error} or \texttt{undefined}
\item Agda performs a \emph{coverage check} to ensure all definitions by pattern matching are complete.
\item Agda performs a \emph{termination check} to ensure all recursive definitions are terminating.
\end{itemize}
Let's look at some examples. Suppose we write an incomplete definition by
pattern matching:
\begin{code}[number]
foo : Bool → Bool
foo true = false
\end{code}
\begin{code}[hide]
foo false = true
\end{code}
Then Agda highlights the definition and gives us an error:
\begin{verbatim}
Incomplete pattern matching for foo. Missing cases:
foo false
when checking the definition of foo
\end{verbatim}
Likewise, if we write a non-terminating definition:
\begin{code}[hide]
{-# NON_TERMINATING #-}
\end{code}
\begin{code}[number]
bar : Nat → Nat
bar x = bar x
\end{code}
Then Agda also highlights the definition and gives us an error:
\begin{verbatim}
Termination checking failed for the following functions:
bar
Problematic calls:
bar x
\end{verbatim}
\marginnote[-5cm]{%
\paragraph{Limitations of coverage and termination checking.}
In general, coverage checking and termination checking are undecidable
problems, so it is impossible to detect all complete
and terminating functions without allowing some false negatives.
Agda instead errs on the side of caution and allows only a subset of
all complete and terminating functions. So it could
happen that you write down a complicated function that is complete and
terminating, yet Agda still throws an error. If that happens, you will
have to write the function in a different way to make it obvious to Agda
that the function is really total. A good rule of thumb is to
use \texttt{Ctrl+c Ctrl+c} to make sure you have cases for all constructors,
and to only make recursive calls on arguments that are \emph{structurally decreasing},
i.e.~that are a subterm of the pattern on the left-hand side of the clause.
When in doubt, it can also pay off to split complex functions into simpler
helper functions that are easier for Agda to analyze.
}
\marginnote{
\begin{exercise}
Is it possible to implement a function of type $\{
A : \ty{} \} \to \List\ A \to \Nat \to A$ in Agda? If yes, do so. If
no, explain why not.
%TODO: give simple version of criteria: all constructors must occur,
%and recursive calls must be on structurally decreasing arguments.
\end{exercise}
}
These restrictions on coverage and termination can sometimes seem
quite restrictive, but it also enables entirely new things to be done
with the type system. In particular, totality of functions is crucial
for working with dependent types, as function calls can appear inside
types. It is also crucial for using Agda as a proof assistant, to rule
out circular proofs. We will discuss both of these topics in more
detail in the following sections.
\subsection{Section summary}
\begin{itemize}
\item Agda is a purely functional programming language much like
Haskell.
\item When defining a datatype in Agda, we need to give the full
type of each constructor (instead of just the types of the arguments
as in Haskell).
\item We can query the Agda typechecker using the commands
\texttt{Ctrl+c Ctrl+l} (load file), \texttt{Ctrl+c Ctrl+d} (deduce
type), and \texttt{Ctrl+c Ctrl+n} (normalise expression).
\item A hole is a part of an Agda program that is not yet complete,
and is entered using \texttt{?} or \texttt{\{!!\}}. We can
interactively develop a program with holes using the commands
\texttt{Ctrl+c Ctrl-,} (information about hole), \texttt{Ctrl+c
Ctrl+c} (case split), and \texttt{Ctrl+c Ctrl+space} (give solution).
\item Types in Agda are themselves values of type $\ty{}$. We can
define polymorphic functions in Agda by adding an argument of type
$\ty{}$.
\item Implicit arguments are declared using curly braces $\{\}$ and
can be omitted from both definition and usage of the function.
\item Agda is a total language, which means that Agda functions will
never crash or fail to terminate. To ensure totality, Agda uses a
coverage checker to check completeness of functions by pattern
matching and a termination checker to check termination of recursive
functions.
\end{itemize}
\section{Dependent types}
Dependent types are types that can refer to --- or \emph{depend on} ---
parts of a program. With dependent types, it is possible to write much
more precise types than in other non-dependent type systems. In
particular, dependent types can be used to encode invariants of our
programs directly into their types, so the type checker can ensure
that they are never broken. In this section we will look into how we
can use dependent types in Agda and why they can be useful.
\subsection{Vectors: lists that know their length}
The prototypical example of a dependent type is the type of
\emph{vectors} $\Vec\ A\ n$. This type contains lists of exactly $n$
elements of type $A$. For example:
\begin{code}[hide]
module TempVec where
data Vec (A : Set) : Nat → Set where
[] : Vec A 0
_::_ : {n : Nat} → A → Vec A n → Vec A (suc n)
infixr 5 _::_
\end{code}
\begin{code}[number]
myVec1 : Vec Nat 5
myVec1 = 1 :: 2 :: 3 :: 4 :: 5 :: []
myVec2 : Vec (Bool → Bool) 2
myVec2 = not :: (λ x → x) :: []
myVec3 : Vec Nat 0
myVec3 = []
\end{code}
\marginnote[-1cm]{%
\paragraph{Overloading of constructors.} Agda allows us to use
the same name for the constructors of different datatypes, for example
$\nil$ can be a constructor of both $\List$ and $\Vec$.
}
%
In fact, the length $n$ does not have to be a literal number, but it
can be any expression of type $\Nat$. So we might as well have written
$\data{Vec}\ \Nat\ (\lit{2}\ \fun{+}\ \lit{3})$ instead of $\data{Vec}\ \Nat\ \lit{5}$.
In a dependently typed language, the return type of a function is
allowed to depend on the inputs of the function. For example, we can
implement a function $\fun{zeroes}$ that takes as input a number $n$,
and produces a vector of zeroes of length $n$:
\begin{code}[number]
zeroes : (n : Nat) → Vec Nat n
zeroes zero = []
zeroes (suc n) = 0 :: zeroes n
\end{code}
The type $(n : \Nat) \to \Vec\ \Nat\ n$ is called a \emph{dependent
function type} (a.k.a. a $\Pi$ type) because the type of the output
depends on the input. Note that the type of the result changes
depending on which clause of the definition we are in: in the first
clause, the input is $\zero$ so the output must have type
$\Vec\ \Nat\ \zero$, while in the second clause the input is $\suc\ n$
so the output must have type $\Vec\ \Nat\ (\suc\ n)$.
\marginnote[-2cm]{
\begin{exercise}
Implement the function
$\fun{downFrom} : (n : \Nat) \to \Vec\ \Nat\ n$ that, given a number
$n$, produces the vector
$(n-1)\ \cons\ (n-2)\ \cons\ \ldots\ \cons\ \lit{0}$. (You'll need to copy
the definition of the $\Vec$ type below to test if your definition
typechecks.)
\end{exercise}
}
We can also define functions where the type of one of the arguments
depends on a previous input. For example:
\begin{code}[hide]
module ThrowAwayPrepend where
\end{code}
\begin{code}[number]
prepend : (n : Nat) → Bool
→ Vec Bool n → Vec Bool (suc n)
prepend n b bs = b :: bs
\end{code}
In fact, this is just a special case of the dependent function type,
thanks to currying: the type of $\fun{prepend}$ can equivalently be
written as $(n : \Nat) \to (\Bool \to \data{Vec}\ \Bool\ n \to
\data{Vec}\ \Bool\ (\suc\ n))$.
If an argument to a function appears in the type of a later argument,
we can make it implicit by using curly braces $\{\}$:
\begin{code}[number]
prepend : {n : Nat} → Bool
→ Vec Bool n → Vec Bool (suc n)
prepend b bs = b :: bs
\end{code}
This allows us for example to write
$\fun{prepend}\ \true\ (\false\ \cons\ \nil)$ instead of
$\fun{prepend}\ \lit{1}\ \true\ (\false\ \cons\ \nil)$. Here Agda infers
automatically from the length of the vector $\false\ \cons\ \nil$ that
$n$ must be $\lit{1}$.
Note that dependent function types use the same syntax as polymorphic
function types. This is no coincidence: in Agda, polymorphic functions
are just a special case of dependent functions where the argument is
of type $\ty{}$.
Let us now take a closer look at the $\Vec$ type\footnote[][-1cm]{Technically,
$\Vec$ is not a type but a \emph{family} of types $\Vec\ A\ n$. This
is also the case for other indexed datatypes we will see later.}
itself. It is defined as follows:
\begin{code}[hide]
module ThrowAwayVec where
\end{code}
\begin{code}[number]
data Vec (A : Set) : Nat → Set where
[] : Vec A 0
_::_ : {n : Nat} → A → Vec A n → Vec A (suc n)
infixr 5 _::_
\end{code}
%
\marginnote[-3cm]{%
\paragraph{Parameters vs.~indices.}
You might wonder why the argument $(A : \ty{})$ appears \emph{before}
the colon in the definition of $\Vec$, while the argument type $\Nat$
appears after it. The reason for this is that $A$ is a
\emph{parameter}, while the argument of type $\Nat$ is an \emph{index}
of the datatype. The main difference is that a parameter is bound once
for the whole definition and must occur uniformly in the return types
of the constructors --- i.e.~the return type of each constructor must
be of the form $\Vec\ A\ \ldots$ --- while each constructor determines
the value of the index individually.
}
%
Just like $\List$, $\Vec$ has two constructors $\nil$ and
$\_\cons\_$. The main difference lies in the \emph{type of the
datatype}: it is no longer $\ty{}$ but instead $\Nat \to \ty{}$,
indicating that it takes one additional argument of type $\Nat$. This
argument is called an \emph{index}, and correspondingly $\Vec$ is
called an \emph{indexed datatype}. This is reflected in the types of
the constructors: $\nil$ constructs a vector of length $\lit{0}$, while
$\_\cons\_$ takes arguments of type $A$ and $\Vec\ A\ n$ and
constructs a vector of length $\suc\ n$, where $n$ is an implicit
argument of the constructor.
\begin{code}[hide]
open TempVec public
\end{code}
We can define functions on $\Vec$ just like we did for $\List$, by
pattern matching on the constructors. For example, we can define
concatenation of vectors as follows:
\begin{code}[number]
_++Vec_ : {A : Set} {m n : Nat}
→ Vec A m → Vec A n → Vec A (m + n)
[] ++Vec ys = ys
(x :: xs) ++Vec ys = x :: (xs ++Vec ys)
\end{code}
Pay close attention to the return type $\Vec\ A\ (m\ +\ n)$ of this
function: it depends on both $m$ and $n$!
So far the length index of $\Vec$ has allowed us to make the types of
operations on lists more precise, but it hasn't really done anything
we couldn't have done in Haskell. So let's try something a bit more
ambitious and implement a function $\fun{head}$ that \emph{only}