0% found this document useful (0 votes)
18 views255 pages

Agda Readthedocs Io en v2.6.2

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views255 pages

Agda Readthedocs Io en v2.6.2

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 255

Agda User Manual

Release 2.6.2

The Agda Team

Jun 19, 2021


Contents

1 Overview 3

2 Getting Started 5
2.1 What is Agda? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Installation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.3 ‘Hello world’ in Agda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
2.4 A Taste of Agda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
2.5 A List of Tutorials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

3 Language Reference 25
3.1 Abstract definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
3.2 Built-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
3.3 Coinduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3.4 Copatterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
3.5 Core language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
3.6 Coverage Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
3.7 Cubical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
3.8 Cumulativity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
3.9 Data Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
3.10 Flat Modality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
3.11 Foreign Function Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
3.12 Function Definitions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
3.13 Function Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
3.14 Generalization of Declared Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
3.15 Guarded Cubical . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
3.16 Implicit Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
3.17 Instance Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
3.18 Irrelevance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
3.19 Lambda Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
3.20 Local Definitions: let and where . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3.21 Lexical Structure . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
3.22 Literal Overloading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
3.23 Mixfix Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
3.24 Module System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
3.25 Mutual Recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
3.26 Pattern Synonyms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
3.27 Positivity Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121

i
3.28 Postulates . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
3.29 Pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
3.30 Prop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
3.31 Record Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
3.32 Reflection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
3.33 Rewriting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 147
3.34 Run-time Irrelevance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
3.35 Safe Agda . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
3.36 Sized Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
3.37 Sort System . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
3.38 Syntactic Sugar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
3.39 Syntax Declarations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
3.40 Telescopes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
3.41 Termination Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 166
3.42 Universe Levels . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
3.43 With-Abstraction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
3.44 Without K . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 183

4 Tools 185
4.1 Automatic Proof Search (Auto) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
4.2 Command-line options . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 188
4.3 Compilers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
4.4 Emacs Mode . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
4.5 Literate Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
4.6 Generating HTML . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
4.7 Generating LaTeX . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 209
4.8 Interface files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
4.9 Library Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226
4.10 Performance debugging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
4.11 Search Definitions in Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230

5 Contribute 233
5.1 Documentation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 233

6 The Agda Team and License 239

7 Indices and tables 243

Bibliography 245

Index 247

ii
Agda User Manual, Release 2.6.2

Contents 1
Agda User Manual, Release 2.6.2

2 Contents
CHAPTER 1

Overview

Note: The Agda User Manual is a work-in-progress and is still incomplete. Contributions, additions and corrections
to the Agda manual are greatly appreciated. To do so, please open a pull request or issue on the GitHub Agda page.

This is the manual for the Agda programming language, its type checking, compilation and editing system and related
resources/tools. The latest PDF version of this manual can be downloaded from GitHub Actions page (instruction on
how to find them <https://github.com/actions/upload-artifact#where-does-the-upload-go>_).
You can find a lot of useful resources on Agda Wiki site, like tutorials, introductions, publications and books. If you’re
new to Agda, you should make use of the resources on Agda Wiki and chapter Getting Started instead of chapter
Language Reference.
A description of the Agda language is given in chapter Language Reference. Guidance on how the Agda editing and
compilation system can be used can be found in chapter Tools.

3
Agda User Manual, Release 2.6.2

4 Chapter 1. Overview
CHAPTER 2

Getting Started

2.1 What is Agda?

Agda is a dependently typed programming language. It is an extension of Martin-Löf’s type theory and is the latest
in the tradition of languages developed in the programming logic group at Chalmers. Other languages in this tradition
are Alf, Alfa, Agda 1, Cayenne. Some other loosely related languages are Coq, Epigram, and Idris.
Because of strong typing and dependent types, Agda can be used as a proof assistant, allowing to prove mathematical
theorems (in a constructive setting) and to run such proofs as algorithms.

2.1.1 Dependent types

Typing for programmers

Type theory is concerned both with programming and logic. We see the type system as a way to express syntactic
correctness. A type correct program has a meaning. Lisp is a totally untyped programming language, and so are its
derivatives like Scheme. In such languages, if f is a function, one can apply it to anything, including itself. This makes
it easy to write programs (almost all programs are well formed), but it also makes it easy to write erroneous programs.
Programs will raise exceptions or loop forever. And it is very difficult to analyze where the problems are.

5
Agda User Manual, Release 2.6.2

Haskell or ML and its derivatives like Standard ML and Caml are typed languages, where functions come with a type
expressing what type of arguments the program expects and what the result type is.
Between these two families of languages come languages, which may or may not have a typing discipline. Most
imperative languages do not come with a rich type system. For example, C is typed, but very loosely (almost everything
is an integer or a variant thereof). Moreover, the typing system does not allow the definition of trees or graphs without
using pointers.
All these languages are examples of partial languages, i.e., the result of computing the value of an expression e of
type T is one of the following:
• the program terminates with a value in the type T
• the program e does not terminate
• the program raises an exception (which has been caused by an incomplete definition – for instance, a function
is only defined for positive integers but is applied to a negative integer.
Agda and other languages based on type theory are total languages in the sense that a program e of type T will
always terminate with a value in T. No runtime error can occur, and no nonterminating programs can be written
(unless explicitly requested by the programmer).

Dependent types

Dependent types are introduced by having families of types indexed by objects in another type. For instance, we can
define the type Vec n of vectors of length n. This is a family of types indexed by objects in Nat (a type parameterized
by natural numbers).
Having dependent types, we must generalize the type of functions and the type of pairs.
The dependent function space (a : A) -> (B a) is the type of the functions taking an argument a in a type
A and a result in B a. Here, A is a type, and B is a family of types indexed by elements in A.
For example, we could define the type of n x m matrices as a type indexed by two natural numbers. Call this type
Mat n m. The function identity, which takes a natural number n as an argument and produces the n x n
identity matrix, is then a function of type identity : (n : Nat) -> (Mat n n).
Remark: We could, of course, just specify the identity function with the type Nat -> Nat -> Mat, where
Mat is the type of matrices, but this is not as precise as the dependent version.
The advantage of using dependent types is that it makes it possible to express properties of programs in the typing
system. We saw above that it is possible to express the type of square matrices of length n. It is also possible to define
the type of operations on matrices so that the lengths are correct. For instance, the type of matrix multiplication is

∀ {i j k} → (Mat i j) -> (Mat j k) -> (Mat i k)

and the type system can check that a program for matrix multiplication really takes arguments of the correct size. It can
also check that matrix multiplication is only applied to matrices, where the number of columns of the first argument is
the same as the number of rows in the second argument.

Dependent types and logic

Thanks to the Curry-Howard correspondence, one can express a logical specification using dependent types. For
example, using only typing it is possible to define:
• equality on natural numbers
• properties of arithmetical operations

6 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

• the type (n : Nat) -> (PrimRoot n) consisting of functions computing primitive root in modular
arithmetic.
Of course, a program of the above type will be more difficult to write than the corresponding program of type Nat
-> Nat, which produces a natural number which is a primitive root. However, the difficulty can be compensated by
the fact that the program is guaranteed to work: it cannot produce something which is not a primitive root.
On a more mathematical level, we can express formulas and prove them using an algorithm. For example, a function
of type (n : Nat) -> (PrimRoot n) is also a proof that every natural number has a primitive root.

2.2 Installation

There are several ways to install Agda:


• Using a released source package from Hackage
• Using a binary package prepared for your platform
• Using the development version from the Git repository
Agda can be installed using different flags (see Installation Flags).

Hint: If you want a sneak peek of Agda without installing it, try the Agda Pad

2.2.1 Installation from source

Prerequisites

You need recent versions of the following programs to compile Agda:


• GHC: https://www.haskell.org/ghc/
– Agda has been tested with GHC 8.0.2, 8.2.2, 8.4.4, 8.6.5, 8.8.4, 8.10.5 and 9.0.1.
• cabal-install: https://www.haskell.org/cabal/
• Alex: https://www.haskell.org/alex/
• Happy: https://www.haskell.org/happy/
• GNU Emacs: http://www.gnu.org/software/emacs/
You should also make sure that programs installed by cabal-install are on your shell’s search path.
Non-Windows users need to ensure that the development files for the C libraries zlib and ncurses are installed (see
http://zlib.net and http://www.gnu.org/software/ncurses/). Your package manager may be able to install these files for
you. For instance, on Debian or Ubuntu it should suffice to run

apt-get install zlib1g-dev libncurses5-dev

as root to get the correct files installed.


Optionally one can also install the ICU library, which is used to implement the --count-clusters flag. Under
Debian or Ubuntu it may suffice to install libicu-dev. Once the ICU library is installed one can hopefully enable the
--count-clusters flag by giving the enable-cluster-counting flag to cabal install.

2.2. Installation 7
Agda User Manual, Release 2.6.2

Installing the agda and the agda-mode programs

After installing the prerequisites you can install the latest released version of Agda from Hackage.

Using cabal

For installing the agda and the agda-mode programs using cabal run the following commands:

cabal update
cabal install Agda

If you use Nix-style Local Builds, by using Cabal ≥ 3.0 or by running cabal v2-install, you’ll get the following
error when compiling with the GHC backend:

Compilation error:

MAlonzo/RTE.hs:13:1: error:
Failed to load interface for ‘Numeric.IEEE’
Use -v to see a list of the files searched for.

This is because packages are sandboxed in $HOME/.cabal/store and you have to explicitly register required
packaged in a GHC environment. This can be done by running the following command:

cabal v2-install --lib Agda ieee754

This will register ieee754 in the GHC default environment.


You may want to keep the default environment clean, e.g. to avoid conflicts with other installed packages. In this case
you can a create separate Agda environment by running:

cabal v2-install --package-env agda --lib Agda ieee754

You then have to set the GHC_ENVIRONMENT when you invoke Agda:

GHC_ENVIRONMENT=agda agda -c hello-world.agda

Note: Actually it is not necessary to register the Agda library, but doing so forces Cabal to install the same version of
ieee754 as used by Agda.

Warning: If you are installing Agda using Cabal on Windows, depending on your system locale setting, cabal
install Agda may fail with an error message:
hGetContents: invalid argument (invalid byte sequence)

If this happens, you can try changing the console code page to UTF-8 using the command:
CHCP 65001

Using stack

For installing the agda and the agda-mode programs using stack run the following commands:

8 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

cabal get Agda-X.Y.Z


cd Agda-X.Y.Z
stack --stack-yaml stack-a.b.c.yaml install

replacing X.Y.Z and a.b.c for the Agda version on Hackage and your GHC version, respectively.

Running the agda-mode program

After installing the agda-mode program using cabal or stack run the following command:

agda-mode setup

The above command tries to set up Emacs for use with Agda via the Emacs mode. As an alternative you can copy the
following text to your .emacs file:

(load-file (let ((coding-system-for-read 'utf-8))


(shell-command-to-string "agda-mode locate")))

It is also possible (but not necessary) to compile the Emacs mode’s files:

agda-mode compile

This can, in some cases, give a noticeable speedup.


Warning: If you reinstall the Agda mode without recompiling the Emacs Lisp files, then Emacs may continue using
the old, compiled files.

2.2.2 Prebuilt Packages and System-Specific Instructions

Arch Linux

The following prebuilt packages are available:


• Agda
• Agda standard library
However, due to significant packaging bugs such as this, you might want to use alternative installation methods.

Debian / Ubuntu

Prebuilt packages are available for Debian and Ubuntu from Karmic onwards. To install:

apt-get install agda-mode

This should install Agda and the Emacs mode.


The standard library is available in Debian and Ubuntu from Lucid onwards. To install:

apt-get install agda-stdlib

More information:
• Agda (Debian)
• Agda standard library (Debian)

2.2. Installation 9
Agda User Manual, Release 2.6.2

• Agda (Ubuntu)
• Agda standard library (Ubuntu)
Reporting bugs:
Please report any bugs to Debian, using:

reportbug -B debian agda


reportbug -B debian agda-stdlib

Fedora

Agda is packaged in Fedora (since before Fedora 18).

yum install Agda

will pull in emacs-agda-mode and ghc-Agda-devel.

FreeBSD

Packages are available from FreshPorts for Agda and Agda standard library.

Nix or NixOS

Agda is part of the Nixpkgs collection that is used by https://nixos.org/nixos. There are two ways to install Agda from
nix:
• The new way: If you are tracking nixos-unstable or nixpkgs-unstable (the default on MacOS) or
you are using NixOS version 20.09 or above then you should be able to install Agda (and the standard library)
via:

nix-env -f "<nixpkgs>" -iE "nixpkgs: (nixpkgs {}).agda.withPackages (p: [ p.


˓→standard-library ])"

agda-mode setup
echo "standard-library" > ~/.agda/defaults

The second command tries to set up the Agda emacs mode. Skip this if you don’t want to set up the emacs
mode. See Installation from source above for more details about agda-mode setup. The third command
sets the standard-library as a default library so it is always available to Agda. If you don’t want to do
this you can omit this step and control library imports on a per project basis using an .agda-lib file in each
project root.
If you don’t want to install the standard library via nix then you can just run:

nix-env -f "<nixpkgs>" -iA agda


agda-mode setup

For more information on the Agda infrastructure in nix, and how to manage and develop Agda libraries with nix,
see https://nixos.org/manual/nixpkgs/unstable/#agda. In particular, the agda.withPackages function can
install more libraries than just the standard library. Alternatively, see Library Management for how to manage
libraries manually.
• The old way (deprecated): As Agda is a Haskell package available from Hackage you can install it like any
other Haskell package:

10 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

nix-env -f "<nixpkgs>" -iA haskellPackages.Agda


agda-mode setup

This approach does not provide any additional support for working with Agda libraries. See Library Manage-
ment for how to manage libraries manually. It also suffers from this open issue which the ‘new way’ does
not.
Nix is extremely flexible and we have only described how to install Agda globally using nix-env. One can also
declare which packages to install globally in a configuration file or pull in Agda and some relevant libraries for a
particular project using nix-shell.

OS X

Homebrew is a free and open-source software package management system that provides prebuilt packages for OS
X. Once it is installed in your system, you are ready to install agda. Open the Terminal app and run the following
commands:

brew install agda


agda-mode setup

This process should take less than a minute, and it installs Agda together with its Emacs mode and its standard library.
For more information about the brew command, please refer to the Homebrew documentation and Homebrew FAQ.
By default, the standard library is installed in the folder /usr/local/lib/agda/. To use the standard library, it is
convenient to add the location of the agda-lib file /usr/local/lib/agda/standard-library.agda-lib
to the ~/.agda/libraries file, and write the line standard-library in the ~/.agda/defaults file. To
do this, run the following commands:

mkdir -p ~/.agda
echo $(brew --prefix)/lib/agda/standard-library.agda-lib >>~/.agda/libraries
echo standard-library >>~/.agda/defaults

Please note that this configuration is not performed automatically. You can learn more about using the standard library
or using a library in general.
It is also possible to install with the command-line option keyword --HEAD. This requires building Agda from source.
To configure the way of editing agda files, follow the section Emacs mode.

Note: If Emacs cannot find the agda-mode executable, it might help to install the exec-path-from-
shell package by doing M-x package-install RET exec-path-from-shell RET and adding the line
(exec-path-from-shell-initialize) to your .emacs file.

Windows

A precompiled version of Agda 2.6.0.1 bundled with Emacs 26.1 with the necessary mathematical fonts, is available
at http://www.cs.uiowa.edu/~astump/agda.

2.2.3 Installation of the Development Version

After getting the development version from the Git repository


• Install the prerequisites

2.2. Installation 11
Agda User Manual, Release 2.6.2

• In the top-level directory of the Agda source tree, run:

cabal update
make install

Note that on a Mac, because ICU is installed in a non-standard location, you need to specify this location on the
command line:

make install CABAL_OPTS='--extra-lib-dirs=/usr/local/opt/icu4c/lib --extra-


˓→include-dirs=/usr/local/opt/icu4c/include'

You can also add the CABAL_OPTS variable to mk/config.mk (see HACKING.md) instead of passing it via
the command line.
To install via stack instead of cabal, copy one of the stack-x.x.x.yaml files of your choice to a
stack.yaml file before running make. For example:

cp stack-8.10.1.yaml stack.yaml
make install

2.2.4 Installation Flags

When installing Agda the following flags can be used:


cpphs
Use cpphs instead of cpp. Default: off.
debug
Enable debugging features that may slow Agda down. Default: off.
enable-cluster-counting
Enable the --count-clusters flag. Note that if enable-cluster-counting is False, then the
--count-clusters flag triggers an error message. Default: off.
optimise-heavily
Optimise Agda heavily. (In this case it might make sense to limit GHC’s memory usage.) Default: off.

2.2.5 Installing multiple versions of Agda

Multiple versions of Agda can be installed concurrently by using the –program-suffix flag. For example:

cabal install Agda-2.6.1 --program-suffix=-2.6.1

will install version 2.6.1 under the name agda-2.6.1. You can then switch to this version of Agda in Emacs via

C-c C-x C-s 2.6.1 RETURN

Switching back to the standard version of Agda is then done by:

C-c C-x C-s RETURN

12 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

2.3 ‘Hello world’ in Agda

This section contains two minimal Agda programs that can be used to test if you have installed Agda correctly: one
for using Agda interactively as a proof assistant, and one for compiling Agda programs to an executable binary. For a
more in-depth introduction to using Agda, see A taste of Agda or the list of tutorials.

2.3.1 Hello, Agda!

Below is is a small ‘hello world’ program in Agda (defined in a file hello.agda).

data Greeting : Set where


hello : Greeting

greet : Greeting
greet = hello

This program defines a data type called Greeting with one constructor hello, and a function definition greet of
type Greeting that returns hello.
To load the Agda file, open it in Emacs and load it by pressing C-c C-l (Ctrl+c followed by Ctrl+l). You should
now see that the code is highlighted and there should be a message *All done*. If this is the case, congratulations!
You have correctly installed Agda and the Agda mode for Emacs. If you also want to compile your Agda programs,
continue with the next section.

2.3.2 Hello, World!

Below is a complete executable ‘hello world’ program in Agda (defined in a file hello-world.agda)

module hello-world where

open import Agda.Builtin.IO using (IO)


open import Agda.Builtin.Unit using (⊤)
open import Agda.Builtin.String using (String)

postulate putStrLn : String → IO ⊤


{-# FOREIGN GHC import qualified Data.Text as T #-}
{-# COMPILE GHC putStrLn = putStrLn . T.unpack #-}

main : IO ⊤
main = putStrLn "Hello world!"

This code is self-contained and has several declarations:


1. Imports of the ÌO, ⊤ and String types from the Agda Builtin library.
2. A postulate of the function type putStrLn.
3. Two pragmas that tell Agda how to compile the function putStrLn.
4. A definition of the function main.
To compile the Agda file, either open it in Emacs and press C-c C-x C-c or run agda --compile
hello-world.agda from the command line. This will create a binary hello-world in the current directory
that prints Hello world!. To find out more about the agda command, use agda --help.

2.3. ‘Hello world’ in Agda 13


Agda User Manual, Release 2.6.2

Note: As you can see from this example, by default Agda includes only minimal library support through the
Builtin modules. The Agda Standard Library provides bindings for most commonly used Haskell functions, includ-
ing putStrLn. For a version of this ‘hello world’ program that uses the standard library, see Building an Executable
Agda Program.

2.4 A Taste of Agda

The objective of this section is to provide a first glimpse of Agda with some small examples. The first one is a
demonstration of dependently typed programming, and the second shows how to use Agda as a proof assistant. Finally,
we build a complete program and compile it to an executable program with the GHC and Javascript backends.

2.4.1 Preliminaries

Before proceeding, make sure that you installed Agda and a compatible version of the standard library.
Agda programs are typically developed interactively, which means that one can type check code which is not yet
complete but contain “holes” which can be filled in later. Editors with support for interactive development of Agda
programs include Emacs via the Emacs mode, Atom via the agda mode for Atom, Visual Studio Code via the agda
mode for VSCode, and Vim via agda-vim.

Hint: If you want a sneak peek of Agda without installing it, try the Agda Pad

Note: In this introduction we use several of Agda’s interactive commands to get information from the typechecker
and manipulate code with holes. Here is a list of the commands that will be used in this tutorial:
• C-c C-l: Load the file and type-check it.
• C-c C-d: Deduce the type of a given expression.
• C-c C-n: Normalise a given expression.
• C-c C-,: Shows the type expected in the current hole, along with the types of any local variables.
• C-c C-c: Case split on a given variable.
• C-c C-SPC: Replace the hole with a given expression, if it has the correct type.
• C-c C-r: Refine the hole by replacing it with a given expression applied to an appropriate number of new
holes.
• C-c C-x C-c (C-x C-c in VS Code): Compile an Agda program.
See Notation for key combinations for a full list of interactive commands (keybindings).

2.4.2 Programming With Dependent Types: Vectors

In the code below, we model the notion of vectors (in the sense of computer science, not in the mathematical sense) in
Agda. Roughly speaking, a vector is a list of objects with a determined length.

14 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

module hello-world-dep where

N
open import Data.Nat using ( ; zero; suc)

data Vec (A : Set) : N


→ Set where
[] : Vec A zero
_::_ : ∀ {n} (x : A) (xs : Vec A n) → Vec A (suc n)

infixr 5 _::_

Paste or type the code above in a new file with name hello-world-dep.agda. Load the file (in Emacs C-c
C-l). This also saves the file. If the agda source code was loaded correctly, you should see that the code is highlighted
and see a message *All done* .

Note: If a file does not type check Agda will complain. Often the cursor will jump to the position of the error, and
the error will (by default) be underlined. Some errors are treated a bit differently, though. If Agda cannot see that a
definition is terminating/productive it will highlight it in light salmon, and if some meta-variable other than the goals
cannot be solved the code will be highlighted in yellow (the highlighting may not appear until after you have reloaded
the file). In case of the latter kinds of errors you can still work with the file, but Agda will (by default) refuse to import
it into another module, and if your functions are not terminating Agda may hang. See Background highlighting for a
full list of the different background colors used by Agda.

Tip: If you do not like the way Agda syntax or errors are highlighted (if you are colour-blind, for instance), then
you can tweak the settings by typing M-x customize-group RET agda2-highlight RET in Emacs (after
loading an Agda file) and following the instructions.

Agda programs are structured into modules. Each Agda file has one top-level module whose name must match the
name of the file, and zero or more nested modules. Each module contains a list of declarations. This example has a
single top-level module called hello-world-dep, which has three declarations:
N
1. An open import statement that imports the datatype and its constructors zero and suc from the module
Data.Nat of the standard library and brings them into scope,
2. A data declaration defining the datatype Vec with two constructors: the empty vector constructor [] and the
cons constructor _::_,
3. And finally an infixr declaration specifying the precedence for the cons operation.

Tip: Agda uses Unicode characters in source files (more specifically: the UTF-8 character encoding), such as , →, N
and :: in this example. Many mathematical symbols can be typed using the corresponding LaTeX command names.
To learn how to enter a unicode character, move the cursor over it and enter M-x describe-char or C-u C-x
=. This displays all information on the character, including how to input it with the Agda input method. For example,
N
to input you can type either \Bbb{N} or \bN. See Unicode input for more details on entering unicode characters.

The datatype Vec

Let us start by looking at the first line of the definition of Vec:

data Vec (A : Set) : N → Set where

2.4. A Taste of Agda 15


Agda User Manual, Release 2.6.2

This line declares a new datatype and names it Vec. The words data and where are keywords, while the part Vec
(A : Set) : N → Set determines the type of Vec.
Vec is not a single type but rather a family of types. This family of types has one parameter A of type Set (which is
N N
the sort of small types, such as , Bool, . . . ) and one index of type (the type of natural numbers). The parameter
A represents the type of the objects of the vector. Meanwhile, the index represents the length of the vector, i.e. the
number of objects it contains.
Together, this line tells us that, for any concrete type B : Set and any natural number m : N, we are declaring a
new type Vec B m, which also belongs to Set.

The constructors [] and _::_

Each constructors of a datatype is declared on a separate line and indented with a strictly positive number of spaces
(in this case two).
We chose the name [] for the first constructor. It represents the empty vector, and its type is Vec A 0, i.e. it is a
vector of length 0.
The second constructor is a mixfix operator named _::_ (pronounced cons). For any number n : N
, it takes as
input an object of A and a vector of length n. As output, it produces a vector with length suc n, the successor of n.
The number n itself is an implicit argument to the constructor _::_.
The final declaration with keyword ìnfixr does not belong to the datatype declaration itself; therefore it is not
indented. It establishes the precedence of the operator _::_.

Tip: You can let Agda infer the type of an expression using the ‘Deduce type’ command (C-c C-d). First press
C-c C-d to open a prompt, enter a term, for instance 3 :: 2 :: 1 :: [], and press return. Agda infers its type and
return the type Vec N
3, meaning that the given term is a vector with 3 objects of type . N

Note: Almost any character can be used in an identifier (like 𝛼, ∧, or ♠, for example). It is therefore necessary to
have spaces between most lexical units. For example 3::2::1::[] is a valid identifier, so we need to write 3 :: 2 ::
1 :: [] instead to make Agda parse it successfully.

The total function lookup

Now that Vec is defined, we continue by defining the lookup function that given a vector and a position, returns
the object of the vector at the given position. In contrast to the lookup function we could define in most (non-
dependently typed) programming languages, this version of the function is total: all calls to it are guaranteed to return
a value in finite time, with no possibility for errors.
To define this function, we use the Fin datatype from the standard library. Fin n is a type with n objects: the
numbers 0 to n-1 (in unary notation zero, suc zero, . . . ), which we use to model the n possible positions in a
vector of length n.
Now create a new file called hello-world-dep-lookup.agda file and type or paste:

module hello-world-dep-lookup where

open import Data.Nat using ( ) N


open import Data.Vec using (Vec; _::_)
open import Data.Fin using (Fin; zero; suc)

(continues on next page)

16 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

(continued from previous page)


variable
A : Set
n : N
lookup : Vec A n → Fin n → A
lookup (a :: as) zero = a
lookup (a :: as) (suc i) = lookup as i

The Vec type that we saw before is actually already in the module Data.Vec of the standard library, so we import it
instead of copying the previous definition.
We have declared A and n as generalizable variables to avoid the declaration of implicit arguments. This allows us to
use A and n in the type of lookup without binding the names explicitly. More explicitly, the full type of lookup
(which we can get by using C-c C-d) is:

lookup : {A : Set} {n : N} → Vec A n → Fin n → A

N
Warning: zero and suc are not the constructors of that we saw before, but rather the constructors of Fin.
Agda allows overloading of constructor names, and disambiguates between them based on the expected type where
they are used.

The definition of the lookup function specifies two cases:


• Either the vector is a :: as and the position is zero, so we return the first object a of the vector.
• Or the vector is a :: as and the position is suc i, so we recursively look up the object at position i in the
tail as of the vector.
There are no cases for the empty vector []. This is no mistake: Agda can determine from the type of lookup that
it is impossible to look up an object in the empty vector, since there is no possible index of type Fin 0. For more
details, see the section on coverage checking.

2.4.3 Agda as a Proof Assistant: Proving Associativity of Addition

In this section we state and prove the associativity of addition on the natural numbers in Agda. In contrast to the
previous section, we build the code line by line. To follow along with this example in Emacs, reload the file after
adding each step by pressing C-c C-l.

Statement of associativity

We start by creating a new file named hello-world-proof.agda. Paste or type the following code:

module hello-world-proof where

Now we import the datatype N and the addition operation _+_, both defined in the Agda Builtin library.
open import Data.Nat using ( ; _+_) N
Next, we import the propositional equality type _≡_ from the module Relation.Binary.
PropositionalEquality.

open import Relation.Binary.PropositionalEquality using (_≡_)

2.4. A Taste of Agda 17


Agda User Manual, Release 2.6.2

Under the Curry-Howard correspondence, the type x ≡ y corresponds to the proposition stating that x and y are
equal objects. By writing a function that returns an object of type x ≡ y, we are proving that the two terms are equal.
Now we can state associativity: given three (possibly different) natural numbers, adding the first to the addition of the
second and the third computes to the same value as adding the addition of the first and the second to the third. We
name this statement +-assoc.

+-assoc : Set
+-assoc = ∀ (x y z : N) → x + (y + z) ≡ (x + y) + z

This is not yet a proof, we have merely written down the statement (or enunciation) of associativity.

Proof of associativity

The statement +-assoc is a member of Set, i.e. it is a type. Now that we have stated the property in a way that
Agda understands, our objective is to prove it. To do so, we have to construct a function of type +-assoc.
N
First, we need to import the constructors zero and suc of the already imported datatype and the constructor refl
(short for reflexivity) and function cong (short for congruence) from the standard library.

open import Data.Nat using (zero; suc)


open import Relation.Binary.PropositionalEquality using (refl; cong)

To prove +-assoc we need to find an object of that type. Here, we name this object +-assoc-proof.

+-assoc-proof : ∀ (x y z : N) → x + (y + z) ≡ (x + y) + z

If we load now the file, Agda gives an error: “The following names are declared but not accompanied by a definition:
+-assoc-proof”. Indeed, we have only declared the type of +-assoc-proof but not yet given a definition. To
build the definition, we need to know more about holes and case splitting.

Holes and case splitting

We can let Agda help us to write the proof by using its interactive mode. To start, we first write a simple clause so the
file can be loaded even if we still do not know the proof. The clause consists of the name of the property, the input
variables, the equals symbol = and the question mark ?.

+-assoc-proof x y z = ?

When we reload the file, Agda no longer throws an error, but instead shows the message *All Goals* with a list of
goals. We have now entered the interactive proving mode. Agda turns our question mark into what is called a hole
{ }0 with a label 0. Each hole stands as a placeholder for a part of the program that is still incomplete and can be
refined or resolved interactively.

Note: You are not supposed to enter a hole such as { }0 manually, Agda takes care of the numbering when you load
the file. To insert a hole, write either ? or {! !} and load the file to make Agda assign a unique number to it.

To get detailed information about a specific hole, put the cursor in it and press C-c C-,. This displays the type of
the hole, as well as the types of all the variables in scope. In this example we get the information that the goal type is
x + (y + z) ≡ x + y + z, and there are three variables x, y, and z in scope, all of type . N
Note: You might wonder why Agda displays the term (x + y) + z as x + y + z (without parenthesis). This
is done because of the infix statement infixl 6 _+_ that was declared in the imported Agda.Builtin.Nat

18 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

module. This declaration means that the _+_ operation is left-associative. More information about mixfix operator
like the arithmetic operations. You can also check this associativity example.

To continue writing our proof, we now pick a variable and perform a case split on it. To do so, put the cursor inside the
hole and press C-c C-c. Agda asks for the name of the pattern variable to case on. Let’s write x and press return.
This replaces the previous clause with two new clauses, one where x has been replaced by zero and another where it
has been replaced by suc x:

+-assoc-proof zero y z = { }0
+-assoc-proof (suc x) y z = { }1

Important: The x in the type signature of +-assoc-proof is not the same as the x pattern variable in the last
clause where suc x is written. The following would also work: +-assoc-proof (suc x1 ) y z = { }1.
The scope of a variable declared in a signature is restricted to the signature itself.

Instead of one hole, we now have two. The first hole has type y + z ≡ y + z, which is easy to resolve. To do
so, put the cursor inside the first hole labeled 0 and press C-c C-r. This replaces the hole by the term refl, which
stands for reflexivity and can be used any time we want to construct a term of type w ≡ w for some term w.

+-assoc-proof zero y z = refl


+-assoc-proof (suc x) y z = { }1

Now we have one hole left to resolve. By putting the cursor in it and pressing C-c C-, again, we get the type of the
hole: suc x + (y + z) ≡ suc x + y + z. Agda has already applied the definition of _+_ to replace the
left-hand side (suc x + y) + z of the equation by suc (x + y + z), and similarly replaced the right-hand
side suc x + (y + z) by suc (x + (y + z)).

Tip: You can use the go-to-definition command by selecting the definition that you want to check eg. _+_
and pressing M-. in Emacs or C-M-\ in Atom. This takes you to the definition of _+_, which is originally defined in
the builtin module Agda.Builtin.Nat.

Tip: You can ask Agda to compute the normal form of a term. To do so, place the cursor in the remaining hole (which
should not contain any text at this point) and press C-c C-n. This prompts you for an expression to normalize. For
example, if we enter (suc x + y) + z we get back suc (x + y + z) as a result.

Proof by induction

If we now look at the type of the remaining hole, we see that both the left-hand side and the right-hand side start with
an application of the constructor suc. In this kind of situation it suffices to prove that the two arguments to suc are
equal. This principle is called congruence of equality _≡_, and it is expressed by the Agda function cong.
To use cong we need to apply it to a function or constructor, in this case suc. If we ask Agda to infer the type of
cong suc by pressing C-c C-d and entering the term, we get back the type {x y : N
} → x ≡ y → suc
x ≡ suc y. In other words, cong suc takes as input a proof of an equality between x and y and produces a new
proof of equality between suc x and suc y. We write cong suc in the hole and again press C-c C-r to refine
the hole. This results in the new line

+-assoc-proof (suc x) y z = cong suc { }2

2.4. A Taste of Agda 19


Agda User Manual, Release 2.6.2

where the new hole with number 2 is of type x + (y + z) ≡ x + y + z.


To finish the proof, we now make a recursive call +-assoc-proof x y z. Note that this has type x + (y +
z) ≡ (x + y) + z, which is exactly what we need. To complete the proof, we type +-assoc-proof x y z
into the hole and solve it with C-c C-space. This replaces the hole with the given term and completes the proof.

Note: When we define a recursive function like this, Agda performs termination checking on it. This is important
to ensure the recursion is well-founded, and hence will not result in an invalid (circular) proof. In this case, the first
argument x is structurally smaller than the first argument suc x on the left-hand side of the clause, hence Agda allows
us to make the recursive call. Because termination is an undecidable property, Agda will not accept all terminating
functions, but only the ones that are mechanically proved to terminate.

The final proof +-assoc-proof is defined as follows:

+-assoc-proof zero y z = refl


+-assoc-proof (suc x) y z = cong suc (+-assoc-proof x y z)

When we reload the file, we see *All Done*. This means that +-assoc-proof is indeed a proof of the statement
+-assoc.
Here is the final code of the ‘Hello world’ proof example, with all imports together at the top of the file:

module hello-world-proof where

N
open import Data.Nat using ( ; zero; suc; _+_)
open import Relation.Binary.PropositionalEquality using (_≡_; refl; cong)

+-assoc : Set
+-assoc = ∀ (x y z : N) → x + (y + z) ≡ (x + y) + z

N
+-assoc-proof : ∀ (x y z : ) → x + (y + z) ≡ (x + y) + z
+-assoc-proof zero y z = refl
+-assoc-proof (suc x) y z = cong suc (+-assoc-proof x y z)

Tip: You can learn more details about proving in the chapter Proof by Induction of the online book Programming
Language Foundations in Agda.

2.4.4 Building an Executable Agda Program

Agda is a dependently typed functional programming language. This means that we can write programs in Agda that
interact with the world. In this section, we write a small ‘Hello world’ program in Agda, compile it, and execute it.
In contrast to the standalone example on the Hello World page, here we make use of the standard library to write a
shorter version of the same program.

Agda Source Code

First, we create a new file named hello-world-prog.agda with Emacs or Atom in a folder that we refer to as
our top-level folder.

module hello-world-prog where

(continues on next page)

20 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

(continued from previous page)


open import IO

main : Main
main = run (putStrLn "Hello, World!")

A quick line-by-line explanation:


• The first line declares the top-level module, named hello-world-prog.
• The second line imports the IO module from the standard library and brings its contents into scope.
• A module exporting a function main of type Main (defined in the IO module of the standard library) can
be compiled to a standalone executable. For example: main = run (putStrLn "Hello, World!")
runs the IO command putStrLn "Hello, World!" and then quits the program.

Compilation with GHC Backend

Once we have loaded the program in Emacs or Atom, we can compile it directly by pressing C-c C-x C-c and
entering GHC. Alternatively, we can open a terminal session, navigate to the top-level folder and run:

agda --compile hello-world-prog.agda

The --compile flag here creates via the GHC backend a binary file in the top-level folder that the computer can
execute.
Finally, we can then run the executable (./hello-world-prog on Unix systems, hello-world-prog.exe
on Windows) from the command line:

$ cd <your top-level folder>


$ ./hello-world-prog
Hello, World!

Compilation with JavaScript Backend

The JavaScript backend translates the Agda source code of the hello-world-prog.agda file to JavaScript code.
From Emacs or Atom, press C-c C-x C-c and enter JS to compile the module to JavaScript. Alternatively, open a
terminal session, navigate to the top-level folder and run:

agda --js hello-world-prog.agda

This creates several .js files in the top-level folder. The file corresponding to our source code has the name jAgda.
hello-world-prog.js.

Hint: The additional --js-optimize flag can be used to make the generated JavaScript code faster but less
readable. Moreover, the --js-minify flag makes the generated JavaScript code smaller and even less readable.

2.4.5 Where to go from here?

There are many books and tutorials on Agda. We recommend this list of tutorials.

2.4. A Taste of Agda 21


Agda User Manual, Release 2.6.2

Join the Agda Community!

Get in touch and join the Agda community, or join the conversation on the Agda Zulip.

2.5 A List of Tutorials

Note: Some of the materials linked on this page have been created for older versions of Agda and might no longer
apply directly to the latest release.

2.5.1 Books on Agda

• Phil Wadler, Wen Kokke, and Jeremy G. Siek (2019). Programming Languages Foundations in Agda
• Aaron Stump (2016). Verified Functional Programming in Agda

2.5.2 Tutorials and lecture notes

• Jesper Cockx (2021). Programming and Proving in Agda. An introduction to Agda for a general audience of
functional programmers. It starts from basic knowledge of Haskell and builds up to using equational reasoning
to formally prove correctness of functional programs.
• Musa Al-hassy (2019). A slow-paced introduction to reflection in Agda.
• Jesper Cockx (2019). Formalize all the things (in Agda).
• Jan Malakhovski (2013). Brutal [Meta]Introduction to Dependent Types in Agda.
• Diviánszky Péter (2012). Agda Tutorial.
• Ana Bove, Peter Dybjer, and Ulf Norell (2009). A Brief Overview of Agda - A Functional Language with
Dependent Types (in TPHOLs 2009) with an example of reflection. Code.
• Andreas Abel (2009). An Introduction to Dependent Types and Agda. Lecture notes used in teaching functional
programming: basic introduction to Agda, Curry-Howard, equality, and verification of optimizations like fusion.
• Ulf Norell and James Chapman (2008). Dependently Typed Programming in Agda. This is aimed at functional
programmers.
• Ana Bove and Peter Dybjer (2008). Dependent Types at Work. A gentle introduction including logic and proofs
of programs.
• Anton Setzer (2008). Lecture notes on Interactive Theorem Proving. Swansea University. These lecture notes
are based on Agda and contain an introduction of Agda for students with a very basic background in logic and
functional programming.

2.5.3 Videos on Agda

• Conor McBride (2014). Introduction to Dependently Typed Programming using Agda. (videos of lectures).
Associated source files, with exercises.
• Daniel Licata (2013). Dependently Typed Programming in Agda (at OPLSS 2013).
• Daniel Peebles (2011). Introduction to Agda. Video of talk from the January 2011 Boston Haskell session at
MIT.

22 Chapter 2. Getting Started


Agda User Manual, Release 2.6.2

2.5.4 Courses using Agda

• Computer Aided Reasoning Material for a 3rd / 4th year course (g53cfr, g54 cfr) at the university of Nottingham
2010 by Thorsten Altenkirch
• Type Theory in Rosario Material for an Agda course in Rosario, Argentina in 2011 by Thorsten Altenkirch
• Software System Design and Implementation , undergrad(?) course at the University of New South Wales by
Manuel Chakravarty.
• Tüübiteooria / Type Theory , graduate course at the University of Tartu by Varmo Vene and James Chapman.
• Advanced Topics in Programming Languages: Dependent Type Systems , course at the University of Pennsyl-
vania by Stephanie Weirich.
• Categorical Logic , course at the University of Cambridge by Samuel Staton.
• Dependently typed functional languages , master level course at EAFIT University by Andrés Sicard-Ramírez.
• Introduction to Dependently Typed Programming using Agda , research level course at the University of Edin-
burgh by Conor McBride.
• Agda , introductory course for master students at ELTE Eötvös Collegium in Budapest by Péter Diviánszky and
Ambrus Kaposi.
• Types for Programs and Proofs , course at Chalmers University of Technology.
• Advanced Functional Programming (in German), course at Ludwig-Maximilians-University Munich.
• Dependently typed metaprogramming (in Agda) , Summer (2013) course at the University of Cambridge by
Conor McBride.
• Computer-Checked Programs and Proofs (COMP 360-1), Dan Licata, Wesleyan, Fall 2013.
• Advanced Functional Programming Fall 2013 (CS410), Conor McBride, Strathclyde, notes from 2015, videos
from 2017.
• Interactive Theorem proving (CS__336), Anton Setzer, Swansea University, Lent 2008.
• Inductive and inductive-recursive definitions in Intuitionistic Type Theory , lectures by Peter Dybjer at the
Oregon Programming Languages Summer School 2015.
• Introduction to Univalent Foundations of Mathematics with Agda , MGS 2019 Martín Hötzel Escardó
• Higher-Dimensional Type Theory (CSCI 8980), courses on homotopy type theory and cubical type theory,
Favonia, the University of Minnesota, Spring 2020
• Correct-by-construction Programming in Agda, a course at the EUTYPES Summer School ‘19 in Ohrid.

2.5.5 Miscellaneous

• Agda has a Wikipedia page

2.5. A List of Tutorials 23


Agda User Manual, Release 2.6.2

24 Chapter 2. Getting Started


CHAPTER 3

Language Reference

3.1 Abstract definitions

Definitions can be marked as abstract, for the purpose of hiding implementation details, or to speed up type-checking
of other parts. In essence, abstract definitions behave like postulates, thus, do not reduce/compute. For instance,
proofs whose content does not matter could be marked abstract, to prevent Agda from unfolding them (which might
slow down type-checking).
As a guiding principle, all the rules concerning abstract are designed to prevent the leaking of implementation
details of abstract definitions. Similar concepts of other programming language include (non-representative sample):
UCSD Pascal’s and Java’s interfaces and ML’s signatures. (Especially when abstract definitions are used in combina-
tion with modules.)

3.1.1 Synopsis

• Declarations can be marked as abstract using the block keyword abstract.


• Outside of abstract blocks, abstract definitions do not reduce, they are treated as postulates, in particular:
– Abstract functions never match, thus, do not reduce.
– Abstract data types do not expose their constructors.
– Abstract record types do not expose their fields nor constructor.
– Other declarations cannot be abstract.
• Inside abstract blocks, abstract definitions reduce while type checking definitions, but not while checking their
type signatures. Otherwise, due to dependent types, one could leak implementation details (e.g. expose reduc-
tion behavior by using propositional equality).
Consequently information from checking the body of a definition cannot leak into its type signature, effectively
disabling type inference for abstract definitions. This means that all abstract definitions need a complete type
signature.

25
Agda User Manual, Release 2.6.2

• The reach of the abstract keyword block extends recursively to the where-blocks of a function and the
declarations inside of a record declaration, but not inside modules declared in an abstract block.

3.1.2 Examples

Integers can be implemented in various ways, e.g. as difference of two natural numbers:

module Integer where

abstract

Z : Set
Z = Nat × Nat
0Z : Z
0Z = 0 , 0

1Z : Z
1Z = 1 , 0

_+Z_ : (x y : Z) → Z
(p , n) +Z (p' , n') = (p + p') , (n + n')

-Z _ : Z → Z
-Z (p , n) = (n , p)

_≡Z_ : (x y : Z) → Set
(p , n) ≡Z (p' , n') = (p + n') ≡ (p' + n)

private
postulate
+comm : ∀ n m → (n + m) ≡ (m + n)

inv Z Z Z
: ∀ x → (x + (- x)) ≡ 0 Z Z
inv Z (p , n) rewrite +comm (p + n) 0 | +comm p n = refl

Using abstract we do not give away the actual representation of integers, nor the implementation of the operations.
Z Z Z Z Z
We can construct them from 0 , 1 , _+ _, and - , but only reason about equality ≡ with the provided lemma
inv .Z
Z
The following property shape-of-0 of the integer zero exposes the representation of integers as pairs. As such,
Z
it is rejected by Agda: when checking its type signature, proj1 x fails to type check since x is of abstract type .
Z
Remember that the abstract definition of does not unfold in type signatures, even when in an abstract block! To
work around this we have to define aliases for the projections functions:

-- A property about the representation of zero integers:

abstract
private
posZ : Z
→ Nat
posZ = proj1

negZ : Z
→ Nat
negZ = proj2

shape-of-0 Z Z Z Z Z
: ∀ (x : ) (is0 : x ≡ 0 ) → posZ x ≡ negZ x
shape-of-0 Z (p , n) refl rewrite +comm p 0 = refl

26 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Z
By requiring shape-of-0 to be private to type-check, leaking of representation details is prevented.

3.1.3 Scope of abstraction

In child modules, when checking an abstract definition, the abstract definitions of the parent module are transparent:
module M1 where
abstract
x : Nat
x = 0

module M2 where
abstract
x-is-0 : x ≡ 0
x-is-0 = refl

Thus, child modules can see into the representation choices of their parent modules. However, parent modules cannot
see like this into child modules, nor can sibling modules see through each others abstract definitions. An exception to
this is anonymous modules, which share abstract scope with their parent module, allowing parent or sibling modules
to see inside their abstract definitions.
The reach of the abstract keyword does not extend into modules:
module Parent where
abstract
module Child where
y : Nat
y = 0
x : Nat
x = 0 -- to avoid "useless abstract" error

y-is-0 : Child.y ≡ 0
y-is-0 = refl

The declarations in module Child are not abstract!

3.1.4 Abstract definitions with where-blocks

Definitions in a where block of an abstract definition are abstract as well. This means, they can see through the
abstractions of their uncles:
module Where where
abstract
x : Nat
x = 0
y : Nat
y = x
where
x≡y : x ≡ 0
x≡y = refl

3.2 Built-ins

3.2. Built-ins 27
Agda User Manual, Release 2.6.2

• Using the built-in types


• The unit type
• The Σ-type
• Lists
• Maybe
• Booleans
• Natural numbers
• Machine words
• Integers
• Floats
• Characters
• Strings
• Equality
• Sorts
• Universe levels
• Sized types
• Coinduction
• IO
• Literal overloading
• Reflection
• Rewriting
• Static values
• Strictness

The Agda type checker knows about, and has special treatment for, a number of different concepts. The most prominent
is natural numbers, which has a special representation as Haskell integers and support for fast arithmetic. The surface
syntax of these concepts are not fixed, however, so in order to use the special treatment of natural numbers (say) you
define an appropriate data type and then bind that type to the natural number concept using a BUILTIN pragma.
Some built-in types support primitive functions that have no corresponding Agda definition. These functions are
declared using the primitive keyword by giving their type signature.

3.2.1 Using the built-in types

While it is possible to define your own versions of the built-in types and bind them using BUILTIN pragmas, it is
recommended to use the definitions in the Agda.Builtin modules. These modules are installed when you install
Agda and so are always available. For instance, built-in natural numbers are defined in Agda.Builtin.Nat. The
standard library and the agda-prelude reexport the definitions from these modules.

28 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.2.2 The unit type

module Agda.Builtin.Unit

The unit type is bound to the built-in UNIT as follows:

record ⊤ : Set where


{-# BUILTIN UNIT ⊤ #-}

Agda needs to know about the unit type since some of the primitive operations in the reflected type checking monad
return values in the unit type.

3.2.3 The Σ-type

module Agda.Builtin.Sigma

The built-in Σ-type of dependent pairs is defined as follows:

record Σ {a b} (A : Set a) (B : A → Set b) : Set (a ⊔ b) where


constructor _,_
field
fst : A
snd : B fst

open Σ public

infixr 4 _,_

{-# BUILTIN SIGMA Σ #-}

3.2.4 Lists

module Agda.Builtin.List

Built-in lists are bound using the LIST built-in:

data List {a} (A : Set a) : Set a where


[] : List A
_::_ : (x : A) (xs : List A) → List A
{-# BUILTIN LIST List #-}
infixr 5 _::_

The constructors are bound automatically when binding the type. Lists are not required to be level polymorphic; List
: Set → Set is also accepted.
As with booleans, the effect of binding the LIST built-in is to let you use primitive functions working with lists, such
as primStringToList and primStringFromList, and letting the GHC backend know to compile the List
type to Haskell lists.

3.2.5 Maybe

3.2. Built-ins 29
Agda User Manual, Release 2.6.2

module Agda.Builtin.Maybe

Built-in maybe type is bound using the MAYBE built-in:

data Maybe {a} (A : Set a) : Set a where


nothing : Maybe A
just : A → Maybe A
{-# BUILTIN MAYBE Maybe #-}

The constructors are bound automatically when binding the type. Maybe is not required to be level polymorphic;
Maybe : Set → Set is also accepted.
As with list, the effect of binding the MAYBE built-in is to let you use primitive functions working with maybes, such
as primStringUncons that returns the head and tail of a string (if it is non empty), and letting the GHC backend
know to compile the Maybe type to Haskell maybes.

3.2.6 Booleans

module Agda.Builtin.Bool where

Built-in booleans are bound using the BOOL, TRUE and FALSE built-ins:

data Bool : Set where


false true : Bool
{-# BUILTIN BOOL Bool #-}
{-# BUILTIN TRUE true #-}
{-# BUILTIN FALSE false #-}

Note that unlike for natural numbers, you need to bind the constructors separately. The reason for this is that Agda
cannot tell which constructor should correspond to true and which to false, since you are free to name them whatever
you like.
The effect of binding the boolean type is that you can then use primitive functions returning booleans, such as built-in
NATEQUALS, and letting the GHC backend know to compile the type to Haskell Bool.

3.2.7 Natural numbers

module Agda.Builtin.Nat

Built-in natural numbers are bound using the NATURAL built-in as follows:

data Nat : Set where


zero : Nat
suc : Nat → Nat
{-# BUILTIN NATURAL Nat #-}

The names of the data type and the constructors can be chosen freely, but the shape of the datatype needs to match the
one given above (modulo the order of the constructors). Note that the constructors need not be bound explicitly.
Binding the built-in natural numbers as above has the following effects:
• The use of natural number literals is enabled. By default the type of a natural number literal will be Nat, but it
can be overloaded to include other types as well.
• Closed natural numbers are represented as Haskell integers at compile-time.

30 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• The compiler backends compile natural numbers to the appropriate number type in the target language.
• Enabled binding the built-in natural number functions described below.

Functions on natural numbers

There are a number of built-in functions on natural numbers. These are special in that they have both an Agda definition
and a primitive implementation. The primitive implementation is used to evaluate applications to closed terms, and the
Agda definition is used otherwise. This lets you prove things about the functions while still enjoying good performance
of compile-time evaluation. The built-in functions are the following:

_+_ : Nat → Nat → Nat


zero + m = m
suc n + m = suc (n + m)
{-# BUILTIN NATPLUS _+_ #-}

_-_ : Nat → Nat → Nat


n - zero = n
zero - suc m = zero
suc n - suc m = n - m
{-# BUILTIN NATMINUS _-_ #-}

_*_ : Nat → Nat → Nat


zero * m = zero
suc n * m = (n * m) + m
{-# BUILTIN NATTIMES _*_ #-}

_==_ : Nat → Nat → Bool


zero == zero = true
suc n == suc m = n == m
_ == _ = false
{-# BUILTIN NATEQUALS _==_ #-}

_<_ : Nat → Nat → Bool


_ < zero = false
zero < suc _ = true
suc n < suc m = n < m
{-# BUILTIN NATLESS _<_ #-}

div-helper : Nat → Nat → Nat → Nat → Nat


div-helper k m zero j = k
div-helper k m (suc n) zero = div-helper (suc k) m n m
div-helper k m (suc n) (suc j) = div-helper k m n j
{-# BUILTIN NATDIVSUCAUX div-helper #-}

mod-helper : Nat → Nat → Nat → Nat → Nat


mod-helper k m zero j = k
mod-helper k m (suc n) zero = mod-helper 0 m n m
mod-helper k m (suc n) (suc j) = mod-helper (suc k) m n j
{-# BUILTIN NATMODSUCAUX mod-helper #-}

The Agda definitions are checked to make sure that they really define the corresponding built-in function. The def-
initions are not required to be exactly those given above, for instance, addition and multiplication can be defined by
recursion on either argument, and you can swap the arguments to the addition in the recursive case of multiplication.
The NATDIVSUCAUX and NATMODSUCAUX are built-ins bind helper functions for defining natural number division
and modulo operations, and satisfy the properties

3.2. Built-ins 31
Agda User Manual, Release 2.6.2

div n (suc m) ≡ div-helper 0 m n m


mod n (suc m) ≡ mod-helper 0 m n m

3.2.8 Machine words

module Agda.Builtin.Word
module Agda.Builtin.Word.Properties

Agda supports built-in 64-bit machine words, bound with the WORD64 built-in:
postulate Word64 : Set
{-# BUILTIN WORD64 Word64 #-}

Machine words can be converted to and from natural numbers using the following primitives:
primitive
primWord64ToNat : Word64 → Nat
primWord64FromNat : Nat → Word64

Converting to a natural number is the trivial embedding, and converting from a natural number gives you the remainder
modulo 264 . The proof of the former theorem:
primitive
primWord64ToNatInjective : ∀ a b → primWord64ToNat a ≡ primWord64ToNat b → a ≡ b

is in the Properties module. The proof of the latter theorem is not primitive, but can be defined in a library using
primTrustMe.
Basic arithmetic operations can be defined on Word64 by converting to natural numbers, performing the correspond-
ing operation, and then converting back. The compiler will optimise these to use 64-bit arithmetic. For instance:
addWord : Word64 → Word64 → Word64
addWord a b = primWord64FromNat (primWord64ToNat a + primWord64ToNat b)

subWord : Word64 → Word64 → Word64


subWord a b = primWord64FromNat ((primWord64ToNat a + 18446744073709551616) -
˓→primWord64ToNat b)

These compile to primitive addition and subtraction on 64-bit words, which in the GHC backend map to operations on
Haskell 64-bit words (Data.Word.Word64).

3.2.9 Integers

module Agda.Builtin.Int

Built-in integers are bound with the INTEGER built-in to a data type with two constructors: one for positive and one
for negative numbers. The built-ins for the constructors are INTEGERPOS and INTEGERNEGSUC.
data Int : Set where
pos : Nat → Int
negsuc : Nat → Int
{-# BUILTIN INTEGER Int #-}
{-# BUILTIN INTEGERPOS pos #-}
{-# BUILTIN INTEGERNEGSUC negsuc #-}

32 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Here negsuc n represents the integer -n - 1. Unlike for natural numbers, there is no special representation of
integers at compile-time since the overhead of using the data type compared to Haskell integers is not that big.
Built-in integers support the following primitive operation (given a suitable binding for String):

primitive
primShowInteger : Int → String

3.2.10 Floats

module Agda.Builtin.Float
module Agda.Builtin.Float.Properties

Floating point numbers are bound with the FLOAT built-in:

postulate Float : Set


{-# BUILTIN FLOAT Float #-}

This lets you use floating point literals. Floats are represented by the type checker as IEEE 754 binary64 double
precision floats, with the restriction that there is exactly one NaN value. The following primitive functions are available
(with suitable bindings for Nat, Bool, String, Int, Maybe_):

primitive
-- Relations
primFloatIsInfinite : Float → Bool
primFloatIsNaN : Float → Bool
primFloatIsNegativeZero : Float → Bool

-- Conversions
primNatToFloat : Nat → Float
primIntToFloat : Int → Float
primFloatToRatio : Float → (Σ Int 𝜆 _ → Int)
primRatioToFloat : Int → Int → Float
primShowFloat : Float → String

-- Operations
primFloatPlus : Float → Float → Float
primFloatMinus : Float → Float → Float
primFloatTimes : Float → Float → Float
primFloatDiv : Float → Float → Float
primFloatPow : Float → Float → Float
primFloatNegate : Float → Float
primFloatSqrt : Float → Float
primFloatExp : Float → Float
primFloatLog : Float → Float
primFloatSin : Float → Float
primFloatCos : Float → Float
primFloatTan : Float → Float
primFloatASin : Float → Float
primFloatACos : Float → Float
primFloatATan : Float → Float
primFloatATan2 : Float → Float → Float
primFloatSinh : Float → Float
primFloatCosh : Float → Float
primFloatTanh : Float → Float
primFloatASinh : Float → Float
(continues on next page)

3.2. Built-ins 33
Agda User Manual, Release 2.6.2

(continued from previous page)


primFloatACosh : Float → Float
primFloatATanh : Float → Float

The primitive binary relations implement their IEEE 754 equivalents, which means that primFloatEquality is
not reflexive, and primFloatInequality and primFloatLess are not total. (Specifically, NaN is not related
to anything, including itself.)
The primFloatIsSafeInteger function determines whether the value is a number that is a safe integer, i.e., is
within the range where the arithmetic operations do not lose precision.
Floating point numbers can be converted to their raw representation using the primitive:

primitive
primFloatToWord64 : Float → Word64

which normalises all NaN to a canonical NaN with an injectivity proof:

primFloatToWord64Injective : ∀ a b → primFloatToWord64 a ≡ primFloatToWord64 b → a


˓→≡ b

in the Properties module. These primitives can be used to define a safe decidable propositional equality with
the --safe option. The function primFloatToWord64 cannot be guaranteed to be consistent across backends,
therefore relying on the specific result may result in inconsistencies.
The rounding operations (primFloatRound, primFloatFloor, and primFloatCeiling) return a value of
type Maybe Int, and return nothing when applied to NaN or the infinities:

primitive
primFloatRound : Float → Maybe Int
primFloatFloor : Float → Maybe Int
primFloatCeiling : Float → Maybe Int

The primFloatDecode function decodes a floating-point number to its mantissa and exponent, normalised such
that the mantissa is the smallest possible integer. It fails when applied to NaN or the infinities, returning nothing.
The primFloatEncode function encodes a pair of a mantissa and exponent to a floating-point number. It fails
when the resulting number cannot be represented as a float. Note that primFloatEncode may result in a loss of
precision.
primitive primFloatDecode : Float → Maybe (Σ Int 𝜆 _ → Int) primFloatEncode : Int → Int → Maybe
Float

3.2.11 Characters

module Agda.Builtin.Char
module Agda.Builtin.Char.Properties

The character type is bound with the CHARACTER built-in:

postulate Char : Set


{-# BUILTIN CHAR Char #-}

Binding the character type lets you use character literals. The following primitive functions are available on characters
(given suitable bindings for Bool, Nat and String):

34 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

primitive
primIsLower : Char → Bool
primIsDigit : Char → Bool
primIsAlpha : Char → Bool
primIsSpace : Char → Bool
primIsAscii : Char → Bool
primIsLatin1 : Char → Bool
primIsPrint : Char → Bool
primIsHexDigit : Char → Bool
primToUpper : Char → Char
primToLower : Char → Char
primCharToNat : Char → Nat
primNatToChar : Nat → Char
primShowChar : Char → String

These functions are implemented by the corresponding Haskell functions from Data.Char (ord and chr for
primCharToNat and primNatToChar). To make primNatToChar total chr is applied to the natural num-
ber modulo 0x110000. Furthermore, to match the behaviour of strings, surrogate code points are mapped to the
replacement character U+FFFD.
Converting to a natural number is the obvious embedding, and its proof:
primitive
primCharToNatInjective : ∀ a b → primCharToNat a ≡ primCharToNat b → a ≡ b

can be found in the Properties module.

3.2.12 Strings

module Agda.Builtin.String
module Agda.Builtin.String.Properties

The string type is bound with the STRING built-in:


postulate String : Set
{-# BUILTIN STRING String #-}

Binding the string type lets you use string literals. The following primitive functions are available on strings (given
suitable bindings for Bool, Char and List):
primitive
primStringUncons : String → Maybe (Σ Char (𝜆 _ → String))
primStringToList : String → List Char
primStringFromList : List Char → String
primStringAppend : String → String → String
primStringEquality : String → String → Bool
primShowString : String → String

String literals can be overloaded.


Converting to and from a list is injective, and their proofs:
primitive
primStringToListInjective : ∀ a b → primStringToList a ≡ primStringToList b → a ≡
˓→b

primStringFromListInjective : ∀ a b → primStringFromList a ≡ primStringFromList b


˓→→ a ≡ b
(continues on next page)

3.2. Built-ins 35
Agda User Manual, Release 2.6.2

(continued from previous page)

can found in the Properties module.


Strings cannot represent unicode surrogate code points (characters in the range U+D800 to U+DFFF). These are
replaced by the unicode replacement character U+FFFD if they appear in string literals.

3.2.13 Equality

module Agda.Builtin.Equality

The identity type can be bound to the built-in EQUALITY as follows

infix 4 _≡_
data _≡_ {a} {A : Set a} (x : A) : A → Set a where
refl : x ≡ x
{-# BUILTIN EQUALITY _≡_ #-}

This lets you use proofs of type lhs ≡ rhs in the rewrite construction.
Other variants of the identity type are also accepted as built-in:

data _≡_ {A : Set} : (x y : A) → Set where


refl : (x : A) → x ≡ x

The type of primEraseEquality has to match the flavor of identity type.

module Agda.Builtin.Equality.Erase

Binding the built-in equality type also enables the primEraseEquality primitive:

primitive
primEraseEquality : ∀ {a} {A : Set a} {x y : A} → x ≡ y → x ≡ y

The function takes a proof of an equality between two values x and y and stays stuck on it until x and y actually
become definitionally equal. Whenever that is the case, primEraseEquality e reduces to refl.
One use of primEraseEquality is to replace an equality proof computed using an expensive function (e.g. a
proof by reflection) by one which is trivially refl on the diagonal.

primTrustMe

module Agda.Builtin.TrustMe

From the primEraseEquality primitive, we can derive a notion of primTrustMe:

primTrustMe : ∀ {a} {A : Set a} {x y : A} → x ≡ y


primTrustMe {x = x} {y} = primEraseEquality unsafePrimTrustMe
where postulate unsafePrimTrustMe : x ≡ y

As can be seen from the type, primTrustMe must be used with the utmost care to avoid inconsistencies. What
makes it different from a postulate is that if x and y are actually definitionally equal, primTrustMe reduces to
refl. One use of primTrustMe is to lift the primitive boolean equality on built-in types like String to something
that returns a proof object:

36 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

eqString : (a b : String) → Maybe (a ≡ b)


eqString a b = if primStringEquality a b
then just primTrustMe
else nothing

With this definition eqString "foo" "foo" computes to just refl.

3.2.14 Sorts

The primitive sorts used in Agda’s type system (Set, Prop, and Set𝜔) are declared using BUILTIN pragmas in the
Agda.Primitive module. These pragmas should not be used directly in other modules, but it is possible to rename
these builtin sorts when importing Agda.Primitive.

{-# BUILTIN TYPE Set #-}


{-# BUILTIN PROP Prop #-}
{-# BUILTIN SETOMEGA Set𝜔 #-}

The primitive sorts Set and Prop are automatically imported at the top of every top-level Agda module, unless the
--no-import-sorts flag is enabled.

3.2.15 Universe levels

module Agda.Primitive

Universe levels are also declared using BUILTIN pragmas. In contrast to the Agda.Builtin modules, the Agda.
Primitive module is auto-imported and thus it is not possible to change the level built-ins. For reference these are
the bindings:

postulate
Level : Set
lzero : Level
lsuc : Level → Level
_⊔_ : Level → Level → Level

{-# BUILTIN LEVEL Level #-}


{-# BUILTIN LEVELZERO lzero #-}
{-# BUILTIN LEVELSUC lsuc #-}
{-# BUILTIN LEVELMAX _⊔_ #-}

3.2.16 Sized types

module Agda.Builtin.Size

The built-ins for sized types are different from other built-ins in that the names are defined by the BUILTIN pragma.
Hence, to bind the size primitives it is enough to write:

{-# BUILTIN SIZEUNIV SizeUniv #-} -- SizeUniv : SizeUniv


{-# BUILTIN SIZE Size #-} -- Size : SizeUniv
{-# BUILTIN SIZELT Size<_ #-} -- Size<_ : ..Size → SizeUniv
{-# BUILTIN SIZESUC ↑_ #-} -- ↑_ : Size → Size
{-# BUILTIN SIZEINF ∞ #-} -- ∞ : Size
{-# BUILTIN SIZEMAX _⊔𝑠 _ #-} -- _⊔𝑠 _ : Size → Size → Size

3.2. Built-ins 37
Agda User Manual, Release 2.6.2

3.2.17 Coinduction

module Agda.Builtin.Coinduction

The following built-ins are used for coinductive definitions:

postulate
∞ : ∀ {a} (A : Set a) → Set a
♯_ : ∀ {a} {A : Set a} → A → ∞ A
♭ : ∀ {a} {A : Set a} → ∞ A → A
{-# BUILTIN INFINITY ∞ #-}
{-# BUILTIN SHARP ♯_ #-}
{-# BUILTIN FLAT ♭ #-}

See Coinduction for more information.

3.2.18 IO

module Agda.Builtin.IO

The sole purpose of binding the built-in IO type is to let Agda check that the main function has the right type (see
Compilers).

postulate IO : Set → Set


{-# BUILTIN IO IO #-}

3.2.19 Literal overloading

module Agda.Builtin.FromNat
module Agda.Builtin.FromNeg
module Agda.Builtin.FromString

The machinery for overloading literals uses built-ins for the conversion functions.

3.2.20 Reflection

module Agda.Builtin.Reflection

The reflection machinery has built-in types for representing Agda programs. See Reflection for a detailed description.

3.2.21 Rewriting

The experimental and totally unsafe rewriting machinery (not to be confused with the rewrite construct) has a built-in
REWRITE for the rewriting relation:

postulate _↦→_ : ∀ {a} {A : Set a} → A → A → Set a


{-# BUILTIN REWRITE _↦→_ #-}

This builtin is bound to the builtin equality type from Agda.Builtin.Equality in Agda.Builtin.
Equality.Rewrite.

38 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.2.22 Static values

The STATIC pragma can be used to mark definitions which should be normalised before compilation. The typical use
case for this is to mark the interpreter of an embedded language as STATIC:

{-# STATIC <Name> #-}

3.2.23 Strictness

module Agda.Builtin.Strict

There are two primitives for controlling evaluation order:

primitive
primForce : ∀ {a b} {A : Set a} {B : A → Set b} (x : A) → (∀ x → B x) → B x
primForceLemma : ∀ {a b} {A : Set a} {B : A → Set b} (x : A) (f : ∀ x → B x) →
˓→primForce x f ≡ f x

where _≡_ is the built-in equality. At compile-time primForce x f evaluates to f x when x is in weak head
normal form (whnf), i.e. one of the following:
• a constructor application
• a literal
• a lambda abstraction
• a type constructor application (data or record type)
• a function type
• a universe (Set _)
Similarly primForceLemma x f, which lets you reason about programs using primForce, evaluates to refl
when x is in whnf. At run-time, primForce e f is compiled (by the GHC backend) to let x = e in seq x
(f x).
For example, consider the following function:

-- pow’ n a = a 2𝑛
pow’ : Nat → Nat → Nat
pow’ zero a = a
pow’ (suc n) a = pow’ n (a + a)

There is a space leak here (both for compile-time and run-time evaluation), caused by unevaluated a + a thunks.
This problem can be fixed with primForce:

infixr 0 _$!_
_$!_ : ∀ {a b} {A : Set a} {B : A → Set b} → (∀ x → B x) → ∀ x → B x
f $! x = primForce x f

-- pow n a = a 2𝑛
pow : Nat → Nat → Nat
pow zero a = a
pow (suc n) a = pow n $! a + a

3.2. Built-ins 39
Agda User Manual, Release 2.6.2

3.3 Coinduction

The corecursive definitions below are accepted if the option --guardedness is active:

{-# OPTIONS --guardedness #-}

(An alternative approach is to use Sized Types.)

3.3.1 Coinductive Records

It is possible to define the type of infinite lists (or streams) of elements of some type A as follows:

record Stream (A : Set) : Set where


coinductive
field
hd : A
tl : Stream A

As opposed to inductive record types, we have to introduce the keyword coinductive before defining the fields
that constitute the record.
It is interesting to note that it is not necessary to give an explicit constructor to the record type Stream.
We can also define pointwise equality (a bisimulation and an equivalence) of a pair of Streams as a coinductive
record:

record _≈_ {A} (xs : Stream A) (ys : Stream A) : Set where


coinductive
field
hd-≡ : hd xs ≡ hd ys
tl-≈ : tl xs ≈ tl ys

Using copatterns we can define a pair of functions on Streams such that one returns the elements in the even positions
and the other the elements in the odd positions:

even : ∀ {A} → Stream A → Stream A


hd (even xs) = hd xs
tl (even xs) = even (tl (tl xs))

odd : ∀ {A} → Stream A → Stream A


odd xs = even (tl xs)

split : ∀ {A} → Stream A → Stream A × Stream A


split xs = even xs , odd xs

as well as a function that merges a pair of Streams by interleaving their elements:

merge : ∀ {A} → Stream A × Stream A → Stream A


hd (merge (xs , ys)) = hd xs
tl (merge (xs , ys)) = merge (ys , tl xs)

Finally, we can prove that merge is a left inverse for split:

merge-split-id : ∀ {A} (xs : Stream A) → merge (split xs) ≈ xs


hd-≡ (merge-split-id _) = refl
tl-≈ (merge-split-id xs) = merge-split-id (tl xs)

40 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.3.2 Old Coinduction

Note: This is the old way of coinduction support in Agda. You are advised to use Coinductive Records instead.

To use coinduction it is recommended that you import the module Coinduction from the standard library. Coinductive
types can then be defined by labelling coinductive occurrences using the delay operator ∞:

N
data Co : Set where
zero : Co N
suc : ∞ Co → Co N N
The type ∞ A can be seen as a suspended computation of type A. It comes with delay and force functions:

♯_ : ∀ {a} {A : Set a} → A → ∞ A
♭ : ∀ {a} {A : Set a} → ∞ A → A

Values of coinductive types can be constructed using corecursion, which does not need to terminate, but has to be
productive. As an approximation to productivity the termination checker requires that corecursive definitions are
guarded by coinductive constructors. As an example the infinite “natural number” can be defined as follows:

inf : Co N
inf = suc (♯ inf)

The check for guarded corecursion is integrated with the check for size-change termination, thus allowing interesting
combinations of inductive and coinductive types. We can for instance define the type of stream processors, along with
some functions:

-- Infinite streams.

data Stream (A : Set) : Set where


_::_ : (x : A) (xs : ∞ (Stream A)) → Stream A

-- A stream processor SP A B consumes elements of A and produces


-- elements of B. It can only consume a finite number of A’s before
-- producing a B.

data SP (A B : Set) : Set where


get : (f : A → SP A B) → SP A B
put : (b : B) (sp : ∞ (SP A B)) → SP A B

-- The function eat is defined by an outer corecursion into Stream B


-- and an inner recursion on SP A B.

eat : ∀ {A B} → SP A B → Stream A → Stream B


eat (get f) (a :: as) = eat (f a) (♭ as)
eat (put b sp) as = b :: ♯ eat (♭ sp) as

-- Composition of stream processors.

_∘_ : ∀ {A B C} → SP B C → SP A B → SP A C
get f1 ∘ put x sp2 = f1 x ∘ ♭ sp2
put x sp1 ∘ sp2 = put x (♯ (♭ sp1 ∘ sp2 ))
sp1 ∘ get f2 = get (𝜆 x → sp1 ∘ f2 x)

It is also possible to define “coinductive families”. It is recommended not to use the delay constructor (♯_) in a

3.3. Coinduction 41
Agda User Manual, Release 2.6.2

constructor’s index expressions. The following definition of equality between coinductive “natural numbers” is dis-
couraged:

N N
data _≈’_ : Co → Co → Set where
zero : zero ≈’ zero
suc : ∀ {m n} → ∞ (m ≈’ n) → suc (♯ m) ≈’ suc (♯ n)

The recommended definition is the following one:

N N
data _≈_ : Co → Co → Set where
zero : zero ≈ zero
suc : ∀ {m n} → ∞ (♭ m ≈ ♭ n) → suc m ≈ suc n

3.4 Copatterns

Consider the following record:

record Enumeration (A : Set) : Set where


constructor enumeration
field
start : A
forward : A → A
backward : A → A

This gives an interface that allows us to move along the elements of a data type A.
For example, we can get the “third” element of a type A:

open Enumeration

3rd : {A : Set} → Enumeration A → A


3rd e = forward e (forward e (forward e (start e)))

Or we can go back 2 positions starting from a given a:

backward-2 : {A : Set} → Enumeration A → A → A


backward-2 e a = backward (backward a)
where
open Enumeration e

Now, we want to use these methods on natural numbers. For this, we need a record of type Enumeration Nat.
Without copatterns, we would specify all the fields in a single expression:

open Enumeration

enum-Nat : Enumeration Nat


enum-Nat = record {
start = 0
; forward = suc
; backward = pred
}
where
pred : Nat → Nat
pred zero = zero
pred (suc x) = x
(continues on next page)

42 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)

test1 : 3rd enum-Nat ≡ 3


test1 = refl

test2 : backward-2 enum-Nat 5 ≡ 3


test2 = refl

Note that if we want to use automated case-splitting and pattern matching to implement one of the fields, we need to
do so in a separate definition.
With copatterns, we can define the fields of a record as separate declarations, in the same way that we would give
different cases for a function:

open Enumeration

enum-Nat : Enumeration Nat


start enum-Nat = 0
forward enum-Nat n = suc n
backward enum-Nat zero = zero
backward enum-Nat (suc n) = n

The resulting behaviour is the same in both cases:

test1 : 3rd enum-Nat ≡ 3


test1 = refl

test2 : backward-2 enum-Nat 5 ≡ 3


test2 = refl

3.4.1 Copatterns in function definitions

In fact, we do not need to start at 0. We can allow the user to specify the starting element.
Without copatterns, we just add the extra argument to the function declaration:

open Enumeration

enum-Nat : Nat → Enumeration Nat


enum-Nat initial = record {
start = initial
; forward = suc
; backward = pred
}
where
pred : Nat → Nat
pred zero = zero
pred (suc x) = x

test1 : 3rd (enum-Nat 10) ≡ 13


test1 = refl

With copatterns, the function argument must be repeated once for each field in the record:

open Enumeration

(continues on next page)

3.4. Copatterns 43
Agda User Manual, Release 2.6.2

(continued from previous page)


enum-Nat : Nat → Enumeration Nat
start (enum-Nat initial) = initial
forward (enum-Nat _) n = suc n
backward (enum-Nat _) zero = zero
backward (enum-Nat _) (suc n) = n

3.4.2 Mixing patterns and co-patterns

Instead of allowing an arbitrary value, we want to limit the user to two choices: 0 or 42.
Without copatterns, we would need an auxiliary definition to choose which value to start with based on the user-
provided flag:

open Enumeration

if_then_else_ : {A : Set} → Bool → A → A → A


if true then x else _ = x
if false then _ else y = y

enum-Nat : Bool → Enumeration Nat


enum-Nat ahead = record {
start = if ahead then 42 else 0
; forward = suc
; backward = pred
}
where
pred : Nat → Nat
pred zero = zero
pred (suc x) = x

With copatterns, we can do the case analysis directly by pattern matching:

open Enumeration

enum-Nat : Bool → Enumeration Nat


start (enum-Nat true) = 42
start (enum-Nat false) = 0
forward (enum-Nat _) n = suc n
backward (enum-Nat _) zero = zero
backward (enum-Nat _) (suc n) = n

Tip: When using copatterns to define an element of a record type, the fields of the record must be in scope. In the
examples above, we use open Enumeration to bring the fields of the record into scope.
Consider the first example:

enum-Nat : Enumeration Nat


start enum-Nat = 0
forward enum-Nat n = suc n
backward enum-Nat zero = zero
backward enum-Nat (suc n) = n

If the fields of the Enumeration record are not in scope (in particular, the start field), then Agda will not be able
to figure out what the first copattern means:

44 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Could not parse the left-hand side start enum-Nat


Operators used in the grammar:
None
when scope checking the left-hand side start enum-Nat in the
definition of enum-Nat

The solution is to open the record before using its fields:

open Enumeration

enum-Nat : Enumeration Nat


start enum-Nat = 0
forward enum-Nat n = suc n
backward enum-Nat zero = zero
backward enum-Nat (suc n) = n

3.5 Core language

A program in Agda consists of a number of declarations written in an *.agda file. A declaration introduces a new
identifier and gives its type and definition. It is possible to declare:
• datatypes
• record types (including coinductive records)
• function definitions (including mixfix operators and abstract definitions)
• modules
• local definitions let and where
• postulates
• variables
• pattern-synonyms
• precedence (fixity)
• pragmas, and
• program options
Declarations have a signature part and a definition part. These can appear separately in the program. Names must
be declared before they are used, but by separating the signature from the definition it is possible to define things in
mutual recursion.

3.5.1 Grammar

At its core, Agda is a dependently typed lambda calculus. The grammar of terms where a represents a generic term is:

a ::= x -- variable
| 𝜆 x → a -- lambda abstraction
| f -- defined function
| (x : a) → a -- function space
| F -- data/record type
(continues on next page)

3.5. Core language 45


Agda User Manual, Release 2.6.2

(continued from previous page)


| c a -- data/record constructor
| s -- sort Seti, Set𝜔+i

3.5.2 Syntax overview

The syntax of an Agda program is defined in terms of three key components:


• Expressions write function bodies and types.
• Declarations declare types, data-types, postulates, records, functions etc.
• Pragmas define program options.
There are also three main levels of syntax, corresponding to different levels of interpretation:
• Concrete is the high-level sugared syntax, it representing exactly what the user wrote (Agda.Syntax.Concrete).
• Abstract, before typechecking (Agda.Syntax.Abstract)
• Internal, the full-intepreted core Agda terms, typechecked; roughly corresponding to (Agda.Syntax.Internal).
The process of translating an *.agda file into an executable has several stages:

*.agda file
==[ parser (Lexer.x + Parser.y) ]==>
Concrete syntax
==[ nicifier (Syntax.Concrete.Definitions) ]==>
'Nice' concrete syntax
==[ scope checking (Syntax.Translation.ConcreteToAbstract) ]==>
Abstract syntax
==[ type checking (TypeChecking.Rules.*) ]==>
Internal syntax
==[ Agda.Compiler.ToTreeless ]==>
Treeless syntax
==[ different backends (Compiler.MAlonzo.*, Compiler.JS.*, ...) ]==>
Source code
==[ different compilers (GHC compiler, ...) ]==>
Executable

The following sections describe these stages in more detail:

3.5.3 Lexer

Lexical analysis (aka tokenization) is the process of converting a sequence of characters (the raw *.agda file) into a
sequence of tokens (strings with a meaning).
The lexer in Agda is generated by Alex, and is an adaptation of GHC’s lexer. The main lexing function lexer is
called by the Agda.Syntax.Parser.Parser to get the next token from the input.

3.5.4 Parser

The parser is the component that takes the output of the lexer and builds a data structure that we will call Concrete
Syntax, while checking for correct syntax.
The parser is generated by Happy.

46 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Example: when a name is a sequence of parts, the lexer just sees it as a string, the parser does the translation in this
step.

3.5.5 Concrete Syntax

The concrete syntax is a raw representation of the program text without any desugaring at all. This is what the parser
produces. The idea is that if we figure out how to keep the concrete syntax around, it can be printed exactly as the user
wrote it.

3.5.6 Nice Concrete Syntax

The Nice Concrete Syntax is a slightly reorganized version of the Concrete Syntax that is easier to deal
with internally. Among other things, it:
• detects mutual blocks
• assembles definitions from their isolated parts
• collects fixity information of mixfix operators and attaches it to definitions
• emits warnings for possibly unintended but still valid declarations, which essentially is dead code such as empty
instance blocks and misplaced pragmas

3.5.7 Abstract Syntax

The translation from Agda.Syntax.Concrete to Agda.Syntax.Abstract involves scope analysis, figuring


out infix operator precedences and tidying up definitions.
The abstract syntax Agda.Syntax.Abstract is the result after desugaring and scope analysis of the concrete
syntax. The type checker works on abstract syntax, producing internal syntax.

3.5.8 Internal Syntax

This is the final stage of syntax before being handed off to one of the backends. Terms are well-scoped and well-typed.
While producing the Internal Syntax, terms are checked for safety. This safety check means termination check
and coverage check for functions, and positivity check for datatypes.
Type-directed operations such as instance resolution and disambiguation of overloaded constructors (different con-
structors with the same name) also happen here.
The internal syntax Agda.Syntax.Internal uses the following haskell datatype to represent the grammar of a
Term presented above.
data Term = Var {-# UNPACK #-} !Int Elims -- ^ @x es@ neutral
| Lam ArgInfo (Abs Term) -- ^ Terms are beta normal. Relevance is
˓→ignored

| Lit Literal
| Def QName Elims -- ^ @f es@, possibly a delta/iota-redex
| Con ConHead ConInfo Elims
-- ^ @c es@ or @record { fs = es }@
-- @es@ allows only Apply and IApply eliminations,
-- and IApply only for data constructors.
| Pi (Dom Type) (Abs Type) -- ^ dependent or non-dependent function space
| Sort Sort
(continues on next page)

3.5. Core language 47


Agda User Manual, Release 2.6.2

(continued from previous page)


| Level Level
| MetaV {-# UNPACK #-} !MetaId Elims

3.5.9 Treeless Syntax

The treeless syntax is intended to be used as input for the compiler backends. It is more low-level than the internal
syntax and is not used for type checking. Some of the features of the treeless syntax are:
• case expressions instead of case trees
• no instantiated datatypes / constructors
For instance, the Glasgow Haskell Compiler (GHC) backend translates the treeless syntax into a proper GHC Haskell
program.
Another backend that may be used is the JavaScript backend, which translates the treeless syntax to JavaScript code.
The treeless representation of the program has A-normal form (ANF). That means that all the case expressions are
targeting a single variable, and all alternatives may only peel off one constructor.
The backends can handle an ANF syntax easier than a syntax of a language where one may case arbitrary expressions
and use deep patterns.

3.6 Coverage Checking

To ensure completeness of definitions by pattern matching, Agda performs a coverage check on each definition by
pattern matching. This page explains how this coverage check works by starting from simple examples and building
up to the general case.

3.6.1 Single match on a non-indexed datatype

When a function definition pattern matches on a single argument of a simple (i.e. non-indexed) datatype, there should
be a clause for each constructor. For example:

data TrafficLight : Set where


red yellow green : TrafficLight

go : TrafficLight → Bool
go red = false
go yellow = false
go green = true

Alternatively, one or more cases may be replaced by a catchall clause that uses a variable pattern or a wildcard pattern
_. In this case, the catchall clause should be last.

go' : TrafficLight → Bool


go' green = true
go' _ = false

Note: When the –exact-split flag is enabled, catchall clauses should be marked explicitly by a catchall pragma ({-#
CATCHALL #-}).

48 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

The coverage check can be turned off for an individual definition by putting a {-# NON_COVERING #-} pragma
immediately in front of the type signature.

{-# NON_COVERING #-}


go'' : TrafficLight → Bool
go'' red = false
go'' green = true

In the special case of a datatype with no constructors (i.e. an empty type), there should be a single absurd clause with
an absurd pattern () and no right-hand side.

data ⊥ : Set where


-- no constructors

magic : {A : Set} → ⊥ → A
magic ()

3.6.2 Matching on multiple arguments

If a function matches on several arguments, there should be a case for each possible combinations of constructors.

sameColor : TrafficLight → TrafficLight → Bool


sameColor red red = true
sameColor red yellow = false
sameColor red green = false
sameColor yellow red = false
sameColor yellow yellow = true
sameColor yellow green = false
sameColor green red = false
sameColor green yellow = false
sameColor green green = true

Again, one or more cases may be replaced by a catchall clause.

sameColor' : TrafficLight → TrafficLight → Bool


sameColor' red red = true
sameColor' yellow yellow = true
sameColor' green green = true
sameColor' _ _ = false

3.6.3 Copattern matching

Functions that return an element of a record type can use copatterns to give the individual fields. The coverage check
will ensure that there is a single case for each field of the record type. For example:

record Person : Set where


field
name : String
age : Nat
open Person

bob : Person
name bob = "Bob"
age bob = 25

3.6. Coverage Checking 49


Agda User Manual, Release 2.6.2

Absurd copatterns or wildcard copatterns are not supported.

3.6.4 Matching on indexed datatypes

When a function definition matches on an argument of an indexed datatype, the following conditions should be satis-
fied:
• For each clause that matches on a constructor pattern c u1 ... u𝑛 , the indices of the type of the pattern
should be unifiable with the indices of the datatype being matched on.
• For each constructor c that does not appear in a clause, unification of the indices of the type of the constructor
with the indices of the datatype should end in a conflict.
For example, consider the definition of the head function on vectors:

data Vec (A : Set) : Nat → Set where


[] : Vec A 0
_::_ : ∀ {n} → A → Vec A n → Vec A (suc n)

head : ∀ {A m} → Vec A (suc m) → A


head (x :: xs) = x

The type of the pattern x :: xs is Vec A (suc n), which is unifiable with the type Vec A (suc m). Mean-
while, unification of the type Vec A 0 of the constructor [] with the type Vec A (suc n) results in a conflict
between 0 and suc n, so there is no case for [].
In case a function matches on several arguments and one or more of them are of indexed datatypes, only those com-
binations of arguments should be considered where the indices do not lead to a conflict. For example, consider the
zipWith function on vectors:

zipWith : ∀ {A B C m} → (A → B → C) → Vec A m → Vec B m → Vec C m


zipWith f [] [] = []
zipWith f (x :: xs) (y :: ys) = f x y :: zipWith f xs ys

Since both input vectors have the same length m, there is are no cases for the combinations where one vector has length
0 and the other has length suc n.
In the special case where unification ends in a conflict for all constructors, there should be a single absurd clase (as for
an empty type). For example:

data Fin : Nat → Set where


zero : ∀ {n} → Fin (suc n)
suc : ∀ {n} → Fin n → Fin (suc n)

no-fin-zero : Fin 0 → ⊥
no-fin-zero ()

In many common cases, absurd clauses may be omitted as long as the remaining clauses reveal sufficient information
to indicate what arguments to case split on. As an example, consider the definition of the lookup function for vectors:

lookup : ∀ {A} {n} → Vec A n → Fin n → A


lookup [] ()
lookup (x :: xs) zero = x
lookup (x :: xs) (suc i) = lookup xs i

This definition pattern matches on both its (explicit) arguments in both the absurd clause and the two regular clauses.
Hence it is allowed to leave out the absurd clause from the definition:

50 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

lookup' : ∀ {A} {n} → Vec A n → Fin n → A


lookup' (x :: xs) zero = x
lookup' (x :: xs) (suc i) = lookup' xs i

Refer to the next section for a precise explanation of when an absurd clause may be omitted.

3.6.5 General case

In the general case, the coverage checker constructs a case tree from the definition given by the user. It then ensures
that the following properties are satisfied:
• The non-absurd clauses of a definition should arise as the leaves of the case tree.
• The absurd clauses of a definition should arise as the internal nodes of the case tree that have no children.
• Absurd clauses may be omitted if removing the corresponding internal nodes from the case tree does not result
in other internal nodes becoming childless.
• Non-absurd clauses may be replaced by catchall clauses if (1) the patterns of those catchall clauses are more
general than the omitted clauses, (2) the added catchall clauses are not more general than any of the clauses that
follow it, and (3) removing the leaves corresponding to the omitted clauses does not result in any internal nodes
becoming childless.
As an example, consider the case tree for the definition of the lookup function defined above:

lookup xs i = case xs of
[] → case i of {}
(x :: xs) → case i of
zero → x
(suc i) → lookup xs i

The absurd clause arises from the case split on i in the branch where xs = [], which leads to zero cases. The two
normal clauses arise from the two leaves of the case tree. If the case [] → case i of {} is removed from the
case tree, all the remaining internal nodes still have at least one child, hence the absurd clause may be left out of the
definition.
For a full formal description of the algorithm that Agda uses to construct a case tree and check coverage of definitions
by pattern matching, refer to the article Elaborating dependent (co)pattern matching: No pattern left behind.

3.7 Cubical

The Cubical mode extends Agda with a variety of features from Cubical Type Theory. In particular, computational
univalence and higher inductive types which hence gives computational meaning to Homotopy Type Theory and
Univalent Foundations. The version of Cubical Type Theory that Agda implements is a variation of the CCHM Cubical
Type Theory where the Kan composition operations are decomposed into homogeneous composition and generalized
transport. This is what makes the general schema for higher inductive types work, following the CHM paper.
To use the cubical mode Agda needs to be run with the --cubical command-line-option or with {-# OPTIONS
--cubical #-} at the top of the file.
The cubical mode adds the following features to Agda:
1. An interval type and path types
2. Generalized transport (transp)
3. Partial elements

3.7. Cubical 51
Agda User Manual, Release 2.6.2

4. Homogeneous composition (hcomp)


5. Glue types
6. Higher inductive types
7. Cubical identity types
There is a standard agda/cubical library for Cubical Agda available at https://github.com/agda/cubical. This
documentation uses the naming conventions of this library, for a detailed list of all of the built-in Cubical Agda files
and primitives see Appendix: Cubical Agda primitives. The main design choices of the core part of the library are
explained in https://homotopytypetheory.org/2018/12/06/cubical-agda/ (lagda rendered version: https://ice1000.org/
2018/12-06-CubicalAgda.html).
The recommended way to get access to the Cubical primitives is to add the following to the top of a file (this assumes
that the agda/cubical library is installed and visible to Agda).
{-# OPTIONS --cubical #-}

open import Cubical.Core.Everything

For detailed install instructions for agda/cubical see: https://github.com/agda/cubical/blob/master/INSTALL.md.


In order to make this library visible to Agda add /path/to/cubical/cubical.agda-lib to .agda/
libraries and cubical to .agda/defaults (where path/to is the absolute path to where the agda/
cubical library has been installed). For details of Agda’s library management see Library Management.
Expert users who do not want to rely on agda/cubical can just add the relevant import statements at the top of
their file (for details see Appendix: Cubical Agda primitives). However, for beginners it is recommended that one uses
at least the core part of the agda/cubical library.
There is also an older version of the library available at https://github.com/Saizan/cubical-demo/. However this is
relying on deprecated features and is not recommended to use.

3.7.1 The interval and path types

The key idea of Cubical Type Theory is to add an interval type I : SSet (the reason this is in SSet is because it
doesn’t support the transp and hcomp operations). A variable i : I intuitively corresponds to a point in the real
unit interval. In an empty context, there are only two values of type I: the two endpoints of the interval, i0 and i1.
i0 : I
i1 : I

Elements of the interval form a De Morgan algebra, with minimum (∧), maximum (∨) and negation (~).
_∧_ : I → I → I
_∨_ : I → I → I
~_ : I → I

All the properties of De Morgan algebras hold definitionally. The endpoints of the interval i0 and i1 are the bottom
and top elements, respectively.
i0 ∨ i = i
i ∨ i1 = i1
i ∨ j = j ∨ i
i0 ∧ i = i0
i1 ∧ i = i
i ∧ j = j ∧ i
~ (~ i) = i
(continues on next page)

52 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


i0 = ~ i1
~ (i ∨ j) = ~ i ∧ ~ j
~ (i ∧ j) = ~ i ∨ ~ j

The core idea of Homotopy Type Theory and Univalent Foundations is a correspondence between paths (as in topol-
ogy) and (proof-relevant) equalities (as in Martin-Löf’s identity type). This correspondence is taken very literally in
Cubical Agda where a path in a type A is represented like a function out of the interval, I → A. A path type is in fact
a special case of the more general built-in heterogeneous path types:

-- PathP : ∀ {l } (A : I → Set l ) → A i0 → A i1 → Set l

-- Non dependent path types


Path : ∀ {l } (A : Set l ) → A → A → Set l
Path A a b = PathP (𝜆 _ → A) a b

The central notion of equality in Cubical Agda is hence heterogeneous equality (in the sense of PathOver in HoTT).
To define paths we use 𝜆-abstractions and to apply them we use regular application. For example, this is the definition
of the constant path (or proof of reflexivity):

refl : ∀ {l } {A : Set l } {x : A} → Path A x x


refl {x = x} = 𝜆 i → x

Although they use the same syntax, a path is not exactly the same as a function. For example, the following is not
valid:

refl : ∀ {l } {A : Set l } {x : A} → Path A x x


refl {x = x} = 𝜆 (i : I) → x

Because of the intuition that paths correspond to equality PathP (𝜆 i → A) x y gets printed as x ≡ y when
A does not mention i. By iterating the path type we can define squares, cubes, and higher cubes in Agda, making the
type theory cubical. For example a square in A is built out of 4 points and 4 lines:

Square : ∀ {l } {A : Set l } {x0 x1 y0 y1 : A} →


x0 ≡ x1 → y0 ≡ y1 → x0 ≡ y0 → x1 ≡ y1 → Set l
Square p q r s = PathP (𝜆 i → p i ≡ q i) r s

Viewing equalities as functions out of the interval makes it possible to do a lot of equality reasoning in a very direct
way:

sym : ∀ {l } {A : Set l } {x y : A} → x ≡ y → y ≡ x
sym p = 𝜆 i → p (~ i)

cong : ∀ {l } {A : Set l } {x y : A} {B : A → Set l } (f : (a : A) → B a) (p : x ≡ y)


→ PathP (𝜆 i → B (p i)) (f x) (f y)
cong f p i = f (p i)

Because of the way functions compute these satisfy some new definitional equalities compared to the standard Agda
definitions:

symInv : ∀ {l } {A : Set l } {x y : A} (p : x ≡ y) → sym (sym p) ≡ p


symInv p = refl

congId : ∀ {l } {A : Set l } {x y : A} (p : x ≡ y) → cong (𝜆 a → a) p ≡ p


congId p = refl

(continues on next page)

3.7. Cubical 53
Agda User Manual, Release 2.6.2

(continued from previous page)


congComp : ∀ {l } {A B C : Set l } (f : A → B) (g : B → C) {x y : A} (p : x ≡ y) →
cong (𝜆 a → g (f a)) p ≡ cong g (cong f p)
congComp f g p = refl

Path types also lets us prove new things are not provable in standard Agda, for example function extensionality (point-
wise equal functions are equal) has an extremely simple proof:

funExt : ∀ {l } {A : Set l } {B : A → Set l } {f g : (x : A) → B x} →


((x : A) → f x ≡ g x) → f ≡ g
funExt p i x = p x i

3.7.2 Transport

While path types are great for reasoning about equality they don’t let us transport along paths between types or even
compose paths, which in particular means that we cannot yet prove the induction principle for paths. In order to
remedy this we also have a built-in (generalized) transport operation transp and homogeneous composition operations
hcomp. The transport operation is generalized in the sense that it lets us specify where it is the identity function.

transp : ∀ {l } (A : I → Set l ) (r : I) (a : A i0) → A i1

There is an additional side condition to be satisfied for a usage of transp to type-check: A should be a constant
function whenever the constraint r = i1 is satisfied. By constant here we mean that A is definitionally equal to 𝜆 _
→ A i0, which in turn requires A i0 and A i1 to be definitionally equal as well.
When r is i1, transp A r will compute as the identity function.

transp A i1 a = a

This is only sound if in such a case A is a trivial path, as the side condition requires.
It might seems strange that the side condition expects r and A to interact, but both of them can depend on any of the
interval variables in scope, so assuming a specific value for r can affect what A looks like.
Some examples of the side condition for different values of r:
• If r is some in-scope variable i, on which A may depend as well, then A only needs to be a constant function
when substituting i1 for i.
• If r is i0 then there is no restrition on A, since the side condition is vacuously true.
• If r is i1 then A must be a constant function.
We can use transp to define regular transport:

transport : ∀ {l } {A B : Set l } → A ≡ B → A → B
transport p a = transp (𝜆 i → p i) i0 a

By combining the transport and min operations we can define the induction principle for paths:

J : ∀ {l } {A : Set l } {x : A} (P : ∀ y → x ≡ y → Set l )
(d : P x refl) {y : A} (p : x ≡ y)
→ P y p
J P d p = transport (𝜆 i → P (p i) (𝜆 j → p (i ∧ j))) d

One subtle difference between paths and the propositional equality type of Agda is that the computation rule for J
does not hold definitionally. If J is defined using pattern-matching as in the Agda standard library then this holds,
however as the path types are not inductively defined this does not hold for the above definition of J. In particular,

54 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

transport in a constant family is only the identity function up to a path which implies that the computation rule for J
only holds up to a path:

transportRefl : ∀ {l } {A : Set l } (x : A) → transport refl x ≡ x


transportRefl {A = A} x i = transp (𝜆 _ → A) i x

JRefl : ∀ {l } {A : Set l } {x : A} (P : ∀ y → x ≡ y → Set l )


(d : P x refl) → J P d refl ≡ d
JRefl P d = transportRefl d

Internally in Agda the transp operation computes by cases on the type, so for example for Σ-types it is computed
elementwise. For path types it is however not yet possible to provide the computation rule as we need some way to
remember the endpoints of the path after transporting it. Furthermore, this must work for arbitrary higher dimensional
cubes (as we can iterate the path types). For this we introduce the “homogeneous composition operations” (hcomp)
that generalize binary composition of paths to n-ary composition of higher dimensional cubes.

3.7.3 Partial elements

In order to describe the homogeneous composition operations we need to be able to write partially specified n-
dimensional cubes (i.e. cubes where some faces are missing). Given an element of the interval r : I there is
a predicate IsOne which represents the constraint r = i1. This comes with a proof that i1 is in fact equal to i1
called 1=1 : IsOne i1. We use Greek letters like 𝜑 or 𝜓 when such an r should be thought of as being in the
domain of IsOne.
Using this we introduce a type of partial elements called Partial 𝜑 A, this is a special version of IsOne 𝜑 → A
with a more extensional judgmental equality (two elements of Partial 𝜑 A are considered equal if they represent
the same subcube, so the faces of the cubes can for example be given in different order and the two elements will still
be considered the same). The idea is that Partial 𝜑 A is the type of cubes in A that are only defined when IsOne
𝜑. There is also a dependent version of this called PartialP 𝜑 A which allows A to be defined only when IsOne
𝜑.

Partial : ∀ {l } → I → Set l → SSet l

PartialP : ∀ {l } → (𝜑 : I) → Partial 𝜑 (Set l ) → SSet l

There is a new form of pattern matching that can be used to introduce partial elements:

partialBool : ∀ i → Partial (i ∨ ~ i) Bool


partialBool i (i = i0) = true
partialBool i (i = i1) = false

The term partialBool i should be thought of a boolean with different values when (i = i0) and (i = i1).
Terms of type Partial 𝜑 A can also be introduced using a Pattern matching lambda.

partialBool' : ∀ i → Partial (i ∨ ~ i) Bool


partialBool' i = 𝜆 { (i = i0) → true
; (i = i1) → false }

When the cases overlap they must agree (note that the order of the cases doesn’t have to match the interval formula
exactly):

partialBool'' : ∀ i j → Partial (~ i ∨ i ∨ (i ∧ j)) Bool


partialBool'' i j = 𝜆 { (i = i1) → true
; (i = i1) (j = i1) → true
; (i = i0) → false }

3.7. Cubical 55
Agda User Manual, Release 2.6.2

Furthermore IsOne i0 is actually absurd.

empty : {A : Set} → Partial i0 A


empty = 𝜆 { () }

Cubical Agda also has cubical subtypes as in the CCHM type theory:

_[_↦→_] : ∀ {l } (A : Set l ) (𝜑 : I) (u : Partial 𝜑 A) → SSet l


A [ 𝜑 ↦→ u ] = Sub A 𝜑 u

A term v : A [ 𝜑 ↦→ u ] should be thought of as a term of type A which is definitionally equal to u : A


when IsOne 𝜑 is satisfied. Any term u : A can be seen as an term of A [ 𝜑 ↦→ u ] which agrees with itself
on 𝜑:

inS : ∀ {l } {A : Set l } {𝜑 : I} (u : A) → A [ 𝜑 ↦→ (𝜆 _ → u) ]

One can also forget that a partial element agrees with u on 𝜑:

outS : ∀ {l } {A : Set l } {𝜑 : I} {u : Partial 𝜑 A} → A [ 𝜑 ↦→ u ] → A

They satisfy the following equalities:

outS (inS a) = a

inS {𝜑 = 𝜑} (outS {𝜑 = 𝜑} a) = a

outS {𝜑 = i1} {u} _ = u 1=1

Note that given a : A [ 𝜑 ↦→ u ] and 𝛼 : IsOne 𝜑, it is not the case that outS a = u 𝛼; however,
underneath the pattern binding (𝜑 = i1), one has outS a = u 1=1.
With all of this cubical infrastructure we can now describe the hcomp operations.

3.7.4 Homogeneous composition

The homogeneous composition operations generalize binary composition of paths so that we can compose multiple
composable cubes.

hcomp : ∀ {l } {A : Set l } {𝜑 : I} (u : I → Partial 𝜑 A) (u0 : A) → A

When calling hcomp {𝜑 = 𝜑} u u0 Agda makes sure that u0 agrees with u i0 on 𝜑. The idea is that u0 is
the base and u specifies the sides of an open box. This is hence an open (higher dimensional) cube where the side
opposite of u0 is missing. The hcomp operation then gives us the missing side opposite of u0. For example binary
composition of paths can be written as:

compPath : ∀ {l } {A : Set l } {x y z : A} → x ≡ y → y ≡ z → x ≡ z
compPath {x = x} p q i = hcomp (𝜆 j → 𝜆 { (i = i0) → x
; (i = i1) → q j })
(p i)

Pictorially we are given p : x ≡ y and q : y ≡ z, and the composite of the two paths is obtained by com-
puting the missing lid of this open square:

x z
^ ^
| |
(continues on next page)

56 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


x | | q j
| |
x ----------> y
p i

In the drawing the direction i goes left-to-right and j goes bottom-to-top. As we are constructing a path from x to
z along i we have i : I in the context already and we put p i as bottom. The direction j that we are doing the
composition in is abstracted in the first argument to hcomp.
Note that the partial element u does not have to specify all the sides of the open box, giving more sides simply gives
you more control on the result of hcomp. For example if we omit the (i = i0) → x side in the definition of
compPath we still get a valid term of type A. However, that term would reduce to hcomp (\ j → \ { () })
x when i = i0 and so that definition would not build a path that starts from x.
We can also define homogeneous filling of cubes as

hfill : ∀ {l } {A : Set l } {𝜑 : I}
(u : ∀ i → Partial 𝜑 A) (u0 : A [ 𝜑 ↦→ u i0 ])
(i : I) → A
hfill {𝜑 = 𝜑} u u0 i = hcomp (𝜆 j → 𝜆 { (𝜑 = i1) → u (i ∧ j) 1=1
; (i = i0) → outS u0 })
(outS u0)

When i is i0 this is u0 and when i is i1 this is hcomp u u0. This can hence be seen as giving us the interior of an
open box. In the special case of the square above hfill gives us a direct cubical proof that composing p with refl
is p.

compPathRefl : ∀ {l } {A : Set l } {x y : A} (p : x ≡ y) → compPath p refl ≡ p


compPathRefl {x = x} {y = y} p j i = hfill (𝜆 _ → 𝜆 { (i = i0) → x
; (i = i1) → y })
(inS (p i))
(~ j)

3.7.5 Glue types

In order to be able to prove the univalence theorem we also have to add “Glue” types. These lets us turn equivalences
between types into paths between types. An equivalence of types A and B is defined as a map f : A → B such
that its fibers are contractible.

fiber : ∀ {l } {A B : Set l } (f : A → B) (y : B) → Set l


fiber {A = A} f y = Σ[ x ∈ A ] f x ≡ y

isContr : ∀ {l } → Set l → Set l


isContr A = Σ[ x ∈ A ] (∀ y → x ≡ y)

record isEquiv {l } {A B : Set l } (f : A → B) : Set l where


field
equiv-proof : (y : B) → isContr (fiber f y)

_≃_ : ∀ {l } (A B : Set l ) → Set l


A ≃ B = Σ[ f ∈ (A → B) ] (isEquiv f)

The simplest example of an equivalence is the identity function.

3.7. Cubical 57
Agda User Manual, Release 2.6.2

idfun : ∀ {l } → (A : Set l ) → A → A
idfun _ x = x

idIsEquiv : ∀ {l } (A : Set l ) → isEquiv (idfun A)


equiv-proof (idIsEquiv A) y =
((y , refl) , 𝜆 z i → z .snd (~ i) , 𝜆 j → z .snd (~ i ∨ j))

idEquiv : ∀ {l } (A : Set l ) → A ≃ A
idEquiv A = (idfun A , idIsEquiv A)

An important special case of equivalent types are isomorphic types (i.e. types with maps going back and forth which
are mutually inverse): https://github.com/agda/cubical/blob/master/Cubical/Foundations/Isomorphism.agda.
As everything has to work up to higher dimensions the Glue types take a partial family of types that are equivalent to
the base type A:

Glue : ∀ {l l '} (A : Set l ) {𝜑 : I}


→ Partial 𝜑 (Σ[ T ∈ Set l ' ] T ≃ A) → Set l '

These come with a constructor and eliminator:

glue : ∀ {l l '} {A : Set l } {𝜑 : I} {Te : Partial 𝜑 (Σ[ T ∈ Set l ' ] T ≃ A)}


→ PartialP 𝜑 T → A → Glue A Te

unglue : ∀ {l l '} {A : Set l } (𝜑 : I) {Te : Partial 𝜑 (Σ[ T ∈ Set l ' ] T ≃ A)}


→ Glue A Te → A

Using Glue types we can turn an equivalence of types into a path as follows:

ua : ∀ {l } {A B : Set l } → A ≃ B → A ≡ B
ua {_} {A} {B} e i = Glue B (𝜆 { (i = i0) → (A , e)
; (i = i1) → (B , idEquiv B) })

The idea is that we glue A together with B when i = i0 using e and B with itself when i = i1 using the identity
equivalence. This hence gives us the key part of univalence: a function for turning equivalences into paths. The other
part of univalence is that this map itself is an equivalence which follows from the computation rule for ua:

ua𝛽 : ∀ {l } {A B : Set l } (e : A ≃ B) (x : A) → transport (ua e) x ≡ e .fst x


ua𝛽 e x = transportRefl (e .fst x)

Transporting along the path that we get from applying ua to an equivalence is hence the same as applying the equiva-
lence. This is what makes it possible to use the univalence axiom computationally in Cubical Agda: we can package
up our equivalences as paths, do equality reasoning using these paths, and in the end transport along the paths in order
to compute with the equivalences.
We have the following equalities:

Glue A {i1} Te = Te 1=1 .fst

unglue 𝜑 (glue t a) = a

glue (\ { (𝜑 = i1) -> g}) (unglue 𝜑 g) = g

unglue i1 {Te} g = Te 1=1 .snd .fst g

glue {𝜑 = i1} t a = t 1=1

58 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

For more results about Glue types and univalence see https://github.com/agda/cubical/blob/master/Cubical/Core/Glue.
agda and https://github.com/agda/cubical/blob/master/Cubical/Foundations/Univalence.agda. For some examples of
what can be done with this for working with binary and unary numbers see https://github.com/agda/cubical/blob/
master/Cubical/Data/BinNat/BinNat.agda.

3.7.6 Higher inductive types

Cubical Agda also lets us directly define higher inductive types as datatypes with path constructors. For example the
circle and torus can be defined as:

data S1 : Set where


base : S1
loop : base ≡ base

data Torus : Set where


point : Torus
line1 : point ≡ point
line2 : point ≡ point
square : PathP (𝜆 i → line1 i ≡ line1 i) line2 line2

Functions out of higher inductive types can then be defined using pattern-matching:

t2c : Torus → S1 × S1
t2c point = (base , base)
t2c (line1 i) = (loop i , base)
t2c (line2 j) = (base , loop j)
t2c (square i j) = (loop i , loop j)

c2t : S1 × S1 → Torus
c2t (base , base) = point
c2t (loop i , base) = line1 i
c2t (base , loop j) = line2 j
c2t (loop i , loop j) = square i j

When giving the cases for the path and square constructors we have to make sure that the function maps the boundary
to the right thing. For instance the following definition does not pass Agda’s typechecker as the boundary of the last
case does not match up with the expected boundary of the square constructor (as the line1 and line2 cases are
mixed up).

c2t_bad : S1 × S1 → Torus
c2t_bad (base , base) = point
c2t_bad (loop i , base) = line2 i
c2t_bad (base , loop j) = line1 j
c2t_bad (loop i , loop j) = square i j

Functions defined by pattern-matching on higher inductive types compute definitionally, for all constructors.

c2t-t2c : ∀ (t : Torus) → c2t (t2c t) ≡ t


c2t-t2c point = refl
c2t-t2c (line1 _) = refl
c2t-t2c (line2 _) = refl
c2t-t2c (square _ _) = refl

t2c-c2t : ∀ (p : S1 × S1 ) → t2c (c2t p) ≡ p


t2c-c2t (base , base) = refl
t2c-c2t (base , loop _) = refl
(continues on next page)

3.7. Cubical 59
Agda User Manual, Release 2.6.2

(continued from previous page)


t2c-c2t (loop _ , base) = refl
t2c-c2t (loop _ , loop _) = refl

By turning this isomorphism into an equivalence we get a direct proof that the torus is equal to two circles.
Torus≡S1 ×S1 : Torus ≡ S1 × S1
Torus≡S1 ×S1 = isoToPath (iso t2c c2t t2c-c2t c2t-t2c)

Cubical Agda also supports parameterized and recursive higher inductive types, for example propositional truncation
(squash types) is defined as:
data ‖_‖ {l } (A : Set l ) : Set l where
|_| : A → ‖ A ‖
squash : ∀ (x y : ‖ A ‖) → x ≡ y

isProp : ∀ {l } → Set l → Set l


isProp A = (x y : A) → x ≡ y

recPropTrunc : ∀ {l } {A : Set l } {P : Set l } → isProp P → (A → P) → ‖ A ‖ → P


recPropTrunc Pprop f | x | = f x
recPropTrunc Pprop f (squash x y i) =
Pprop (recPropTrunc Pprop f x) (recPropTrunc Pprop f y) i

For many more examples of higher inductive types see: https://github.com/agda/cubical/tree/master/Cubical/HITs.

3.7.7 Cubical identity types and computational HoTT/UF

As mentioned above the computation rule for J does not hold definitionally for path types. Cubical Agda solves
this by introducing a cubical identity type. The https://github.com/agda/cubical/blob/master/Cubical/Core/Id.agda file
exports all of the primitives for this type, including the notation _≡_ and a J eliminator that computes definitionally
on refl.
The cubical identity type and the path type are equivalent, so all of the results for one can be transported to the other
one (using univalence). Using this we have implemented an interface to HoTT/UF which provides the user with the
key primitives of Homotopy Type Theory and Univalent Foundations implemented using cubical primitives under the
hood. This hence gives an axiom free version of HoTT/UF which computes properly.
module Cubical.Core.HoTT-UF where

open import Cubical.Core.Id public


using ( _≡_ -- The identity type.
; refl -- Unfortunately, pattern matching on refl is not
˓→available.

; J -- Until it is, you have to use the induction principle J.

; transport -- As in the HoTT Book.


; ap
; _∙_
; _−1

; _≡⟨_⟩_ -- Standard equational reasoning.


; _

; funExt -- Function extensionality


-- (can also be derived from univalence).
(continues on next page)

60 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)

; Σ -- Sum type. Needed to define contractible types,


˓→ equivalences
; _,_ -- and univalence.
; pr1 -- The eta rule is available.
; pr2

; isProp -- The usual notions of proposition, contractible type, set.


; isContr
; isSet

; isEquiv -- A map with contractible fibers


-- (Voevodsky's version of the notion).
; _≃_ -- The type of equivalences between two given types.
; EquivContr -- A formulation of univalence.

; ‖_‖ -- Propositional truncation.


; |_| -- Map into the propositional truncation.
; ‖‖-isProp -- A truncated type is a proposition.
; ‖‖-recursion -- Non-dependent elimination.
; ‖‖-induction -- Dependent elimination.
)

In order to get access to only the HoTT/UF primitives start a file as follows:

{-# OPTIONS --cubical #-}

open import Cubical.Core.HoTT-UF

However, even though this interface exists it is still recommended that one uses the cubical identity types unless one
really need J to compute on refl. The reason for this is that the syntax for path types does not work for the identity
types, making many proofs more involved as the only way to reason about them is using J. Furthermore, the path
types satisfy many useful definitional equalities that the identity types don’t.

3.7.8 References

Cyril Cohen, Thierry Coquand, Simon Huber and Anders Mörtberg; “Cubical Type Theory: a constructive
interpretation of the univalence axiom”.
Thierry Coquand, Simon Huber, Anders Mörtberg; “On Higher Inductive Types in Cubical Type Theory”.

3.7.9 Appendix: Cubical Agda primitives

The Cubical Agda primitives and internals are exported by a series of files found in the lib/prim/Agda/
Builtin/Cubical directory of Agda. The agda/cubical library exports all of these primitives with the names
used throughout this document. Experts might find it useful to know what is actually exported as there are quite a few
primitives available that are not really exported by agda/cubical, so the goal of this section is to list the contents
of these files. However, for regular users and beginners the agda/cubical library should be sufficient and this
section can safely be ignored.
The key file with primitives is Agda.Primitive.Cubical. It exports the following BUILTIN, primitives and
postulates:

3.7. Cubical 61
Agda User Manual, Release 2.6.2

{-# BUILTIN INTERVAL I #-} -- I : SSet


{-# BUILTIN IZERO i0 #-}
{-# BUILTIN IONE i1 #-}

infix 30 primINeg
infixr 20 primIMin primIMax

primitive
primIMin : I → I → I -- _∧_
primIMax : I → I → I -- _∨_
primINeg : I → I -- ~_

{-# BUILTIN ISONE IsOne #-} -- IsOne : I → SSet

postulate
itIsOne : IsOne i1 -- 1=1
IsOne1 : ∀ i j → IsOne i → IsOne (primIMax i j)
IsOne2 : ∀ i j → IsOne j → IsOne (primIMax i j)

{-# BUILTIN ITISONE itIsOne #-}


{-# BUILTIN ISONE1 IsOne1 #-}
{-# BUILTIN ISONE2 IsOne2 #-}
{-# BUILTIN PARTIAL Partial #-}
{-# BUILTIN PARTIALP PartialP #-}

postulate
isOneEmpty : ∀ {a} {A : Partial i0 (Set a)} → PartialP i0 A
{-# BUILTIN ISONEEMPTY isOneEmpty #-}

primitive
primPOr : ∀ {a} (i j : I) {A : Partial (primIMax i j) (Set a)}
→ PartialP i (𝜆 z → A (IsOne1 i j z)) → PartialP j (𝜆 z → A (IsOne2 i j
˓→z))

→ PartialP (primIMax i j) A

-- Computes in terms of primHComp and primTransp


primComp : ∀ {a} (A : (i : I) → Set (a i)) (𝜑 : I) → (∀ i → Partial 𝜑 (A i)) → (a
˓→: A i0) → A i1

syntax primPOr p q u t = [ p ↦→ u , q ↦→ t ]

primitive
primTransp : ∀ {a} (A : (i : I) → Set (a i)) (𝜑 : I) → (a : A i0) → A i1
primHComp : ∀ {a} {A : Set a} {𝜑 : I} → (∀ i → Partial 𝜑 A) → A → A

The Path types are exported by Agda.Builtin.Cubical.Path:

postulate
PathP : ∀ {l } (A : I → Set l ) → A i0 → A i1 → Set l

{-# BUILTIN PATHP PathP #-}

infix 4 _≡_
_≡_ : ∀ {l } {A : Set l } → A → A → Set l
_≡_ {A = A} = PathP (𝜆 _ → A)

{-# BUILTIN PATH _≡_ #-}

62 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

The Cubical subtypes are exported by Agda.Builtin.Cubical.Sub:

{-# BUILTIN SUB Sub #-}

postulate
inc : ∀ {l } {A : Set l } {𝜑} (x : A) → Sub A 𝜑 (𝜆 _ → x)

{-# BUILTIN SUBIN inS #-}

primitive
primSubOut : ∀ {l } {A : Set l } {𝜑 : I} {u : Partial 𝜑 A} → Sub _ 𝜑 u → A

The Glue types are exported by Agda.Builtin.Cubical.Glue:

record isEquiv {l l '} {A : Set l } {B : Set l '} (f : A → B) : Set (l ⊔ l ') where


field
equiv-proof : (y : B) → isContr (fiber f y)
infix 4 _≃_

_≃_ : ∀ {l l '} (A : Set l ) (B : Set l ') → Set (l ⊔ l ')


A ≃ B = Σ (A → B) \ f → (isEquiv f)

equivFun : ∀ {l l '} {A : Set l } {B : Set l '} → A ≃ B → A → B


equivFun e = fst e

equivProof : ∀ {la lt} (T : Set la) (A : Set lt) → (w : T ≃ A) → (a : A)


→ ∀ 𝜓 → (Partial 𝜓 (fiber (w .fst) a)) → fiber (w .fst) a
equivProof A B w a 𝜓 fb = contr' {A = fiber (w .fst) a} (w .snd .equiv-proof a) 𝜓 fb
where
contr' : ∀ {l } {A : Set l } → isContr A → (𝜑 : I) → (u : Partial 𝜑 A) → A
contr' {A = A} (c , p) 𝜑 u = hcomp (𝜆 i → 𝜆 { (𝜑 = i1) → p (u 1=1) i
; (𝜑 = i0) → c }) c

{-# BUILTIN EQUIV _≃_ #-}


{-# BUILTIN EQUIVFUN equivFun #-}
{-# BUILTIN EQUIVPROOF equivProof #-}

primitive
primGlue : ∀ {l l '} (A : Set l ) {𝜑 : I}
→ (T : Partial 𝜑 (Set l ')) → (e : PartialP 𝜑 (𝜆 o → T o ≃ A))
→ Set l '
prim^glue : ∀ {l l '} {A : Set l } {𝜑 : I}
→ {T : Partial 𝜑 (Set l ')} → {e : PartialP 𝜑 (𝜆 o → T o ≃ A)}
→ PartialP 𝜑 T → A → primGlue A T e
prim^unglue : ∀ {l l '} {A : Set l } {𝜑 : I}
→ {T : Partial 𝜑 (Set l ')} → {e : PartialP 𝜑 (𝜆 o → T o ≃ A)}
→ primGlue A T e → A
primFaceForall : (I → I) → I

-- pathToEquiv proves that transport is an equivalence (for details


-- see Agda.Builtin.Cubical.Glue). This is needed internally.
{-# BUILTIN PATHTOEQUIV pathToEquiv #-}

Note that the Glue types are uncurried in agda/cubical to make them more pleasant to use:

Glue : ∀ {l l '} (A : Set l ) {𝜑 : I}


→ (Te : Partial 𝜑 (Σ[ T ∈ Set l ' ] T ≃ A))
→ Set l '
(continues on next page)

3.7. Cubical 63
Agda User Manual, Release 2.6.2

(continued from previous page)


Glue A Te = primGlue A (𝜆 x → Te x .fst) (𝜆 x → Te x .snd)

The Agda.Builtin.Cubical.Id exports the cubical identity types:

postulate
Id : ∀ {l } {A : Set l } → A → A → Set l

{-# BUILTIN ID Id #-}


{-# BUILTIN CONID conid #-}

primitive
primDepIMin : _
primIdFace : ∀ {l } {A : Set l } {x y : A} → Id x y → I
primIdPath : ∀ {l } {A : Set l } {x y : A} → Id x y → x ≡ y

primitive
primIdJ : ∀ {l l '} {A : Set l } {x : A} (P : ∀ y → Id x y → Set l ') →
P x (conid i1 (𝜆 i → x)) → ∀ {y} (p : Id x y) → P y p

primitive
primIdElim : ∀ {a c} {A : Set a} {x : A}
(C : (y : A) → Id x y → Set c) →
((𝜑 : I) (y : A [ 𝜑 ↦→ (𝜆 _ → x) ])
(w : (x ≡ outS y) [ 𝜑 ↦→ (𝜆 { (𝜑 = i1) → \ _ → x}) ]) →
C (outS y) (conid 𝜑 (outS w))) →
{y : A} (p : Id x y) → C y p

3.8 Cumulativity

3.8.1 Basics

Since version 2.6.1, Agda supports optional cumulativity of universes under the --cumulativity flag.

{-# OPTIONS --cumulativity #-}

When the --cumulativity flag is enabled, Agda uses the subtyping rule Set i =< Set j whenever i =< j.
For example, in addition to its usual type Set, Nat also has the type Set1 and even Set i for any i : Level.

_ : Set
_ = Nat

_ : Set1
_ = Nat

_ : ∀ {i} → Set i
_ = Nat

With cumulativity is enabled, one can implement lifting to a higher universe as the identity function.

lift : ∀ {a b} → Set a → Set (a ⊔ b)


lift x = x

64 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.8.2 Example usage: N-ary functions

In Agda without cumulativity, it is tricky to define a universe-polymorphic N-ary function type A → A → ... →
A → B because the universe level depends on whether the number of arguments is zero:

module Without-Cumulativity where

N-ary-level : Level → Level → Nat → Level


N-ary-level l 1 l 2 zero = l2
N-ary-level l 1 l 2 (suc n) = l 1 ⊔ N-ary-level l 1 l 2 n

N-ary : ∀ {l 1 l 2 } n → Set l 1 → Set l 2 → Set (N-ary-level l 1 l 2 n)


N-ary zero A B = B
N-ary (suc n) A B = A → N-ary n A B

In contrast, in Agda with cumulativity one can always work with the highest possible universe level. This makes it
much easier to define the type of N-ary functions.

module With-Cumulativity where

N-ary : Nat → Set l 1 → Set l 2 → Set (l 1 ⊔ l 2 )


N-ary zero A B = B
N-ary (suc n) A B = A → N-ary n A B

curry𝑛 : (Vec A n → B) → N-ary n A B


curry𝑛 {n = zero} f = f []
curry𝑛 {n = suc n} f = 𝜆 x → curry𝑛 𝜆 xs → f (x :: xs)

_$𝑛 _ : N-ary n A B → (Vec A n → B)


f $𝑛 [] = f
f $𝑛 (x :: xs) = f x $𝑛 xs

∀𝑛 : ∀ {A : Set l 1 } n → N-ary n A (Set l 2 ) → Set (l 1 ⊔ l 2 )


∀𝑛 zero P = P
∀𝑛 (suc n) P = ∀ x → ∀𝑛 n (P x)

3.8.3 Limitations

Currently cumulativity only enables subtyping between universes, but not between any other types containing uni-
verses. For example, List Set is not a subtype of List Set1 . Agda also does not have cumulativity for any other
types containing universe levels, so List {lzero} Nat is not a subtype of List {lsuc lzero} Nat. Such
rules might be added in a future version of Agda.

3.8.4 Constraint solving

When working in Agda with cumulativity, universe level metavariables are often underconstrained. For example, the
expression List Nat could mean List {lzero} Nat, but also List {lsuc lzero} Nat, or indeed List
{i} Nat for any i : Level.
Currently Agda uses the following heuristic to instantiate universe level metavariables. At the end of each type signa-
ture, each mutual block, or declaration that is not part of a mutual block, Agda instantiates all universe level metavari-
ables that are unbounded from above. A metavariable _l : Level is unbounded from above if all unsolved
constraints that mention the metavariable are of the form a𝑖 =< _l : Level, and _l does not occur in the type
of any other unsolved metavariables. For each metavariable that satisfies these conditions, it is instantiated to a1 ⊔
a2 ⊔ ... ⊔ a𝑛 where a1 =< _l : Level, . . . , a𝑛 =< _l : Level are all constraints that mention _l.

3.8. Cumulativity 65
Agda User Manual, Release 2.6.2

The heuristic as described above is considered experimental and is subject to change in future versions of Agda.

3.9 Data Types

3.9.1 Simple datatypes

Example datatypes

In the introduction we already showed the definition of the data type of natural numbers (in unary notation):

data Nat : Set where


zero : Nat
suc : Nat → Nat

We give a few more examples. First the data type of truth values:

data Bool : Set where


true : Bool
false : Bool

The True set represents the trivially true proposition:

data True : Set where


tt : True

The False set has no constructor and hence no elements. It represents the trivially false proposition:

data False : Set where

Another example is the data type of non-empty binary trees with natural numbers in the leaves:

data BinTree : Set where


leaf : Nat → BinTree
branch : BinTree → BinTree → BinTree

Finally, the data type of Brouwer ordinals:

data Ord : Set where


zeroOrd : Ord
sucOrd : Ord → Ord
limOrd : (Nat → Ord) → Ord

General form

The general form of the definition of a simple datatype D is the following

data D : Set𝑖 where


c1 : A1
...
c𝑛 : A𝑛

The name D of the data type and the names c1 , . . . , c𝑛 of the constructors must be new w.r.t. the current signature and
context, and the types A1 , . . . , A𝑛 must be function types ending in D, i.e. they must be of the form

66 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(y1 : B1 ) → ... → (y𝑚 : B𝑚 ) → D

3.9.2 Parametrized datatypes

Datatypes can have parameters. They are declared after the name of the datatype but before the colon, for example:

data List (A : Set) : Set where


[] : List A
_::_ : A → List A → List A

3.9.3 Indexed datatypes

In addition to parameters, datatypes can also have indices. In contrast to parameters which are required to be the same
for all constructors, indices can vary from constructor to constructor. They are declared after the colon as function
arguments to Set. For example, fixed-length vectors can be defined by indexing them over their length of type Nat:

data Vector (A : Set) : Nat → Set where


[] : Vector A zero
_::_ : {n : Nat} → A → Vector A n → Vector A (suc n)

Notice that the parameter A is bound once for all constructors, while the index {n : Nat} must be bound locally
in the constructor _::_.
Indexed datatypes can also be used to describe predicates, for example the predicate Even : Nat → Set can be
defined as follows:

data Even : Nat → Set where


even-zero : Even zero
even-plus2 : {n : Nat} → Even n → Even (suc (suc n))

General form

The general form of the definition of a (parametrized, indexed) datatype D is the following

data D (x1 : P1 ) ... (x𝑘 : P𝑘 ) : (y1 : Q1 ) → ... → (y𝑙 : Q𝑙 ) → Set l where


c1 : A1
...
c𝑛 : A𝑛

where the types A1 , . . . , A𝑛 are function types of the form

(z1 : B1 ) → ... → (z𝑚 : B𝑚 ) → D x1 ... x𝑘 t1 ... t𝑙

3.9.4 Strict positivity

When defining a datatype D, Agda poses an additional requirement on the types of the constructors of D, namely that
D may only occur strictly positively in the types of their arguments.
Concretely, for a datatype with constructors c1 : A1 , . . . , c𝑛 : A𝑛 , Agda checks that each A𝑖 has the form

3.9. Data Types 67


Agda User Manual, Release 2.6.2

(y1 : B1 ) → ... → (y𝑚 : B𝑚 ) → D

where an argument types B𝑖 of the constructors is either


• non-inductive (a side condition) and does not mention D at all,
• or inductive and has the form

(z1 : C1 ) → ... → (z𝑘 : C𝑘 ) → D

where D must not occur in any C𝑗 .


The strict positivity condition rules out declarations such as

data Bad : Set where


bad : (Bad → Bad) → Bad
-- A B C
-- A is in a negative position, B and C are OK

since there is a negative occurrence of Bad in the type of the argument of the constructor. (Note that the corresponding
data type declaration of Bad is allowed in standard functional languages such as Haskell and ML.).
Non strictly-positive declarations are rejected because they admit non-terminating functions.
If the positivity check is disabled, so that a similar declaration of Bad is allowed, it is possible to construct a term of
the empty type, even without recursion.

{-# OPTIONS --no-positivity-check #-}

data ⊥ : Set where

data Bad : Set where


bad : (Bad → ⊥) → Bad

self-app : Bad → ⊥
self-app (bad f) = f (bad f)

absurd : ⊥
absurd = self-app (bad self-app)

For more general information on termination see Termination Checking.

3.10 Flat Modality

The flat/crisp attribute @♭/@flat is an idempotent comonadic modality modeled after Spatial Type Theory and Crisp
Type Theory. It is similar to a necessity modality.
We can define ♭ A as a type for any (@♭ A : Set l) via an inductive definition:

data ♭ {@♭ l : Level} (@♭ A : Set l) : Set l where


con : (@♭ x : A) → ♭ A

counit : {@♭ l : Level} {@♭ A : Set l} → ♭ A → A


counit (con x) = x

When trying to provide a @♭ arguments only other @♭ variables will be available, the others will be marked as @⊤ in
the context. For example the following will not typecheck:

68 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

unit : {@♭ l : Level} {@♭ A : Set l} → A → ♭ A


unit x = con x

3.10.1 Pattern Matching on @♭

Agda allows matching on @♭ arguments by default. When matching on a @♭ argument the flat status gets propagated
to the arguments of the constructor
data _⊎_ (A B : Set) : Set where
inl : A → A ⊎ B
inr : B → A ⊎ B

flat-sum : {@♭ A B : Set} → (@♭ x : A ⊎ B) → ♭ A ⊎ ♭ B


flat-sum (inl x) = inl (con x)
flat-sum (inr x) = inr (con x)

When refining @♭ variables the equality also needs to be provided as @♭


flat-subst : {@♭ A : Set} {P : A → Set} (@♭ x y : A) (@♭ eq : x ≡ y) → P x → P y
flat-subst x .x refl p = p

if we simply had (eq : x ≡ y) the code would be rejected.


Pattern matching on @♭ arguments can be disabled entirely by using the --no-flat-split flag
{-# OPTIONS --no-flat-split #-}

Subtyping of flat function spaces

Normally, if f : (@♭ x : A) → B then we have 𝜆 x → f x : (x : A) → B but not f : (x


: A) → B. When the option --subtyping is enabled, Agda will make use of the subtyping rule (@♭ x :
A) → B <: (x : A) → B, so there is no need for eta-expanding the function f.

3.11 Foreign Function Interface

• Compiler Pragmas
• Haskell FFI
– The FOREIGN pragma
– The COMPILE pragma
– Using Haskell Types from Agda
– Using Haskell functions from Agda
– Using Agda functions from Haskell
– Polymorphic functions
– Level-polymorphic types
– Handling typeclass constraints

3.11. Foreign Function Interface 69


Agda User Manual, Release 2.6.2

• JavaScript FFI

3.11.1 Compiler Pragmas

There are two backend-generic pragmas used for the FFI:

{-# COMPILE <Backend> <Name> <Text> #-}


{-# FOREIGN <Backend> <Text> #-}

The COMPILE pragma associates some information <Text> with a name <Name> defined in the same module, and
the FOREIGN pragma associates <Text> with the current top-level module. This information is interpreted by the
specific backend during compilation (see below). These pragmas were added in Agda 2.5.3.

3.11.2 Haskell FFI

Note: This section applies to the GHC Backend.

The FOREIGN pragma

The GHC backend interprets FOREIGN pragmas as inline Haskell code and can contain arbitrary code (including
import statements) that will be added to the compiled module. For instance:

{-# FOREIGN GHC import Data.Maybe #-}

{-# FOREIGN GHC


data Foo = Foo | Bar Foo

countBars :: Foo -> Integer


countBars Foo = 0
countBars (Bar f) = 1 + countBars f
#-}

The COMPILE pragma

There are four forms of COMPILE annotations recognized by the GHC backend

{-# COMPILE GHC <Name> = <HaskellCode> #-}


{-# COMPILE GHC <Name> = type <HaskellType> #-}
{-# COMPILE GHC <Name> = data <HaskellData> (<HsCon1> | .. | <HsConN>) #-}
{-# COMPILE GHC <Name> as <HaskellName> #-}

The first three tells the compiler how to compile a given Agda definition and the last exposes an Agda definition under
a particular Haskell name allowing Agda libraries to be used from Haskell.

Using Haskell Types from Agda

In order to use a Haskell function from Agda its type must be mapped to an Agda type. This mapping can be configured
using the type and data forms of the COMPILE pragma.

70 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Opaque types

Opaque Haskell types are exposed to Agda by postulating an Agda type and associating it to the Haskell type using
the type form of the COMPILE pragma:
{-# FOREIGN GHC import qualified System.IO #-}

postulate FileHandle : Set


{-# COMPILE GHC FileHandle = type System.IO.Handle #-}

This tells the compiler that the Agda type FileHandle corresponds to the Haskell type System.IO.Handle and
will enable functions using file handles to be used from Agda.

Data types

Non-opaque Haskell data types can be mapped to Agda datatypes using the data form of the COMPILED pragma:
data Maybe (A : Set) : Set where
nothing : Maybe A
just : A → Maybe A

{-# COMPILE GHC Maybe = data Maybe (Nothing | Just) #-}

The compiler checks that the types of the Agda constructors match the types of the corresponding Haskell constructors
and that no constructors have been left out (on either side).

Built-in Types

The GHC backend compiles certain Agda built-in types to special Haskell types. The mapping between Agda built-in
types and Haskell types is as follows:

Agda Built-in Haskell Type


NAT Integer
INTEGER Integer
STRING Data.Text.Text
CHAR Char
BOOL Bool
FLOAT Double

Warning: Haskell code manipulating Agda natural numbers as integers must take care to avoid negative values.

Warning: Agda FLOAT values have only one logical NaN value. At runtime, there might be multiple different
NaN representations present. All such NaN values must be treated equal by FFI calls.

Using Haskell functions from Agda

Once a suitable mapping between Haskell types and Agda types has been set up, Haskell functions whose types map
to Agda types can be exposed to Agda code with a COMPILE pragma:

3.11. Foreign Function Interface 71


Agda User Manual, Release 2.6.2

open import Agda.Builtin.IO


open import Agda.Builtin.String
open import Agda.Builtin.Unit

{-# FOREIGN GHC


import qualified Data.Text.IO as Text
import qualified System.IO as IO
#-}

postulate
stdout : FileHandle
hPutStrLn : FileHandle → String → IO ⊤
{-# COMPILE GHC stdout = IO.stdout #-}
{-# COMPILE GHC hPutStrLn = Text.hPutStrLn #-}

The compiler checks that the type of the given Haskell code matches the type of the Agda function. Note that the
COMPILE pragma only affects the runtime behaviour–at type-checking time the functions are treated as postulates.

Warning: It is possible to give Haskell definitions to defined (non-postulate) Agda functions. In this case the
Agda definition will be used at type-checking time and the Haskell definition at runtime. However, there are
no checks to ensure that the Agda code and the Haskell code behave the same and discrepancies may lead to
undefined behaviour.
This feature can be used to let you reason about code involving calls to Haskell functions under the assumption
that you have a correct Agda model of the behaviour of the Haskell code.

Using Agda functions from Haskell

Since Agda 2.3.4 Agda functions can be exposed to Haskell code using the as form of the COMPILE pragma:

module IdAgda where

idAgda : ∀ {A : Set} → A → A
idAgda x = x

{-# COMPILE GHC idAgda as idAgdaFromHs #-}

This tells the compiler that the Agda function idAgda should be compiled to a Haskell function called
idAgdaFromHs. Without this pragma, functions are compiled to Haskell functions with unpredictable names and,
as a result, cannot be invoked from Haskell. The type of idAgdaFromHs will be the translated type of idAgda.
The compiled and exported function idAgdaFromHs can then be imported and invoked from Haskell like this:

-- file UseIdAgda.hs
module UseIdAgda where

import MAlonzo.Code.IdAgda (idAgdaFromHs)


-- idAgdaFromHs :: () -> a -> a

idAgdaApplied :: a -> a
idAgdaApplied = idAgdaFromHs ()

72 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Polymorphic functions

Agda is a monomorphic language, so polymorphic functions are modeled as functions taking types as arguments.
These arguments will be present in the compiled code as well, so when calling polymorphic Haskell functions they
have to be discarded explicitly. For instance,

postulate
ioReturn : {A : Set} → A → IO A

{-# COMPILE GHC ioReturn = \ _ x -> return x #-}

In this case compiled calls to ioReturn will still have A as an argument, so the compiled definition ignores its first
argument and then calls the polymorphic Haskell return function.

Level-polymorphic types

Level-polymorphic types face a similar problem to polymorphic functions. Since Haskell does not have universe levels
the Agda type will have more arguments than the corresponding Haskell type. This can be solved by defining a Haskell
type synonym with the appropriate number of phantom arguments. For instance:

data Either {a b} (A : Set a) (B : Set b) : Set (a ⊔ b) where


left : A → Either A B
right : B → Either A B

{-# FOREIGN GHC type AgdaEither a b = Either #-}


{-# COMPILE GHC Either = data AgdaEither (Left | Right) #-}

Handling typeclass constraints

There is (currently) no way to map a Haskell type with type class constraints to an Agda type. This means that
functions with class constraints cannot be used from Agda. However, this can be worked around by wrapping class
constraints in Haskell data types, and providing Haskell functions using explicit dictionary passing.
For instance, suppose we have a simple GUI library in Haskell:

module GUILib where


class Widget w
setVisible :: Widget w => w -> Bool -> IO ()

data Window
instance Widget Window
newWindow :: IO Window

To use this library from Agda we first define a Haskell type for widget dictionaries and map this to an Agda type
Widget:

{-# FOREIGN GHC import GUILib #-}


{-# FOREIGN GHC data WidgetDict w = Widget w => WidgetDict #-}

postulate
Widget : Set → Set
{-# COMPILE GHC Widget = type WidgetDict #-}

We can then expose setVisible as an Agda function taking a Widget instance argument:

3.11. Foreign Function Interface 73


Agda User Manual, Release 2.6.2

postulate
setVisible : {w : Set} {{_ : Widget w}} → w → Bool → IO ⊤
{-# COMPILE GHC setVisible = \ _ WidgetDict -> setVisible #-}

Note that the Agda Widget argument corresponds to a WidgetDict argument on the Haskell side. When we match
on the WidgetDict constructor in the Haskell code, the packed up dictionary will become available for the call to
setVisible.
The window type and functions are mapped as expected and we also add an Agda instance packing up the Widget
Window Haskell instance into a WidgetDict:

postulate
Window : Set
newWindow : IO Window
instance WidgetWindow : Widget Window
{-# COMPILE GHC Window = type Window #-}
{-# COMPILE GHC newWindow = newWindow #-}
{-# COMPILE GHC WidgetWindow = WidgetDict #-}

We can then write code like this:

openWindow : IO Window
openWindow = newWindow >>= 𝜆 w →
setVisible w true >>= 𝜆 _ →
return w

3.11.3 JavaScript FFI

The JavaScript backend recognizes COMPILE pragmas of the following form:

{-# COMPILE JS <Name> = <JsCode> #-}

where <Name> is a postulate, constructor, or data type. The code for a data type is used to compile pattern matching
and should be a function taking a value of the data type and a table of functions (corresponding to case branches)
indexed by the constructor names. For instance, this is the compiled code for the List type, compiling lists to
JavaScript arrays:

data List {a} (A : Set a) : Set a where


[] : List A
_::_ : (x : A) (xs : List A) → List A

{-# COMPILE JS List = function(x,v) {


if (x.length < 1) {
return v["[]"]();
} else {
return v["_::_"](x[0], x.slice(1));
}
} #-}
{-# COMPILE JS [] = Array() #-}
{-# COMPILE JS _::_ = function (x) { return function(y) { return Array(x).concat(y); };
˓→} #-}

74 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.12 Function Definitions

3.12.1 Introduction

A function is defined by first declaring its type followed by a number of equations called clauses. Each clause consists
of the function being defined applied to a number of patterns, followed by = and a term called the right-hand side. For
example:

not : Bool → Bool


not true = false
not false = true

Functions are allowed to call themselves recursively, for example:

twice : Nat → Nat


twice zero = zero
twice (suc n) = suc (suc (twice n))

3.12.2 General form

The general form for defining a function is

f : (x1 : A1 ) → ... → (x𝑛 : A𝑛 ) → B


f p1 ... p𝑛 = d
...
f q1 ... q𝑛 = e

where f is a new identifier, p𝑖 and q𝑖 are patterns of type A𝑖 , and d and e are expressions.
The declaration above gives the identifier f the type (x1 : A1 ) → ... → (x𝑛 : A𝑛 ) → B and f is
defined by the defining equations. Patterns are matched from top to bottom, i.e., the first pattern that matches the
actual parameters is the one that is used.
By default, Agda checks the following properties of a function definition:
• The patterns in the left-hand side of each clause should consist only of constructors and variables.
• No variable should occur more than once on the left-hand side of a single clause.
• The patterns of all clauses should together cover all possible inputs of the function, see Coverage Checking.
• The function should be terminating on all possible inputs, see Termination Checking.

3.12.3 Special patterns

In addition to constructors consisting of constructors and variables, Agda supports two special kinds of patterns: dot
patterns and absurd patterns.

Dot patterns

A dot pattern (also called inaccessible pattern) can be used when the only type-correct value of the argument is
determined by the patterns given for the other arguments. The syntax for a dot pattern is .t.
As an example, consider the datatype Square defined as follows

3.12. Function Definitions 75


Agda User Manual, Release 2.6.2

data Square : Nat → Set where


sq : (m : Nat) → Square (m * m)

Suppose we want to define a function root : (n : Nat) → Square n → Nat that takes as its argu-
ments a number n and a proof that it is a square, and returns the square root of that number. We can do so as follows:

root : (n : Nat) → Square n → Nat


root .(m * m) (sq m) = m

Notice that by matching on the argument of type Square n with the constructor sq : (m : Nat) →
Square (m * m), n is forced to be equal to m * m.
In general, when matching on an argument of type D i1 ... i𝑛 with a constructor c : (x1 : A1 ) →
... → (x𝑚 : A𝑚 ) → D j1 ... j𝑛 , Agda will attempt to unify i1 ... i𝑛 with j1 ... j𝑛 .
When the unification algorithm instantiates a variable x with value t, the corresponding argument of the function
can be replaced by a dot pattern .t. Using a dot pattern is optional, but can help readability. The following are also
legal definitions of root:
Since Agda 2.4.2.4:

root1 : (n : Nat) → Square n → Nat


root1 _ (sq m) = m

Since Agda 2.5.2:

root2 : (n : Nat) → Square n → Nat


root2 n (sq m) = m

In the case of root2 , n evaluates to m * m in the body of the function and is thus equivalent to

root3 : (n : Nat) → Square n → Nat


root3 _ (sq m) = let n = m * m in m

Absurd patterns

Absurd patterns can be used when none of the constructors for a particular argument would be valid. The syntax for
an absurd pattern is ().
As an example, if we have a datatype Even defined as follows

data Even : Nat → Set where


even-zero : Even zero
even-plus2 : {n : Nat} → Even n → Even (suc (suc n))

then we can define a function one-not-even : Even 1 → ⊥ by using an absurd pattern:

one-not-even : Even 1 → ⊥
one-not-even ()

Note that if the left-hand side of a clause contains an absurd pattern, its right-hand side must be omitted.
In general, when matching on an argument of type D i1 ... i𝑛 with an absurd pattern, Agda will attempt for
each constructor c : (x1 : A1 ) → ... → (x𝑚 : A𝑚 ) → D j1 ... j𝑛 of the datatype D to
unify i1 ... i𝑛 with j1 ... j𝑛 . The absurd pattern will only be accepted if all of these unifications end in a
conflict.

76 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

As-patterns

As-patterns (or @-patterns) can be used to name a pattern. The name has the same scope as normal pattern
variables (i.e. the right-hand side, where clause, and dot patterns). The name reduces to the value of the named
pattern. For example:

module _ {A : Set} (_<_ : A → A → Bool) where


merge : List A → List A → List A
merge xs [] = xs
merge [] ys = ys
merge xs@(x :: xs1 ) ys@(y :: ys1 ) =
if x < y then x :: merge xs1 ys
else y :: merge xs ys1

As-patterns are properly supported since Agda 2.5.2.

3.12.4 Case trees

Internally, Agda represents function definitions as case trees. For example, a function definition

max : Nat → Nat → Nat


max zero n = n
max m zero = m
max (suc m) (suc n) = suc (max m n)

will be represented internally as a case tree that looks like this:

max m n = case m of
zero → n
suc m' → case n of
zero → suc m'
suc n' → suc (max m' n')

Note that because Agda uses this representation of the function max, the clause max m zero = m does not hold
definitionally (i.e. as a reduction rule). If you would try to prove that this equation holds, you would not be able to
write refl:

data _≡_ {A : Set} (x : A) : A → Set where


refl : x ≡ x

-- Does not work!


lemma : (m : Nat) → max m zero ≡ m
lemma = refl

Clauses which do not hold definitionally are usually (but not always) the result of writing clauses by hand instead of
using Agda’s case split tactic. These clauses are highlighted by Emacs.
The --exact-split flag causes Agda to raise an error whenever a clause in a definition by pattern matching cannot
be made to hold definitionally. Specific clauses can be excluded from this check by means of the {-# CATCHALL
#-} pragma.
For instance, the above definition of max will be rejected when using the --exact-split flag because its second
clause does not to hold definitionally.
When using the --exact-split flag, catch-all clauses have to be marked as such, for instance:

3.12. Function Definitions 77


Agda User Manual, Release 2.6.2

eq : Nat → Nat → Bool


eq zero zero = true
eq (suc m) (suc n) = eq m n
{-# CATCHALL #-}
eq _ _ = false

The --no-exact-split flag can be used to override a global --exact-split in a file, by adding a pragma
{-# OPTIONS --no-exact-split #-}. This option is enabled by default.

3.13 Function Types

Function types are written (x : A) → B, or in the case of non-dependent functions simply A → B. For instance,
the type of the addition function for natural numbers is:

Nat → Nat → Nat

and the type of the addition function for vectors is:

(A : Set) → (n : Nat) → (u : Vec A n) → (v : Vec A n) → Vec A n

where Set is the type of sets and Vec A n is the type of vectors with n elements of type A. Arrows between
consecutive hypotheses of the form (x : A) may also be omitted, and (x : A) (y : A) may be shortened
to (x y : A):

(A : Set) (n : Nat)(u v : Vec A n) → Vec A n

Functions are constructed by lambda abstractions, which can be either typed or untyped. For instance, both expressions
below have type (A : Set) → A → A (the second expression checks against other types as well):

example1 = \ (A : Set)(x : A) → x
example2 = \ A x → x

You can also use the Unicode symbol 𝜆 (type “\lambda” in the Emacs Agda mode) instead of \\.
The application of a function f : (x : A) → B to an argument a : A is written f a and the type of this
is B[x := a].

3.13.1 Notational conventions

Function types:

prop1 : ((x : A) (y : B) → C) is-the-same-as ((x : A) → (y : B) → C)


prop2 : ((x y : A) → C) is-the-same-as ((x : A)(y : A) → C)
prop3 : (forall (x : A) → C) is-the-same-as ((x : A) → C)
prop4 : (forall x → C) is-the-same-as ((x : _) → C)
prop5 : (forall x y → C) is-the-same-as (forall x → forall y → C)

You can also use the Unicode symbol ∀ (type “\all” in the Emacs Agda mode) instead of forall.
Functional abstraction:

(\x y → e) is-the-same-as (\x → (\y → e))

Functional application:

78 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(f a b) is-the-same-as ((f a) b)

3.14 Generalization of Declared Variables

• Overview
• Nested generalization
• Placement of generalized bindings
• Instance and irrelevant variables
• Importing and exporting variables
• Interaction
• Modalities

3.14.1 Overview

Since version 2.6.0, Agda supports implicit generalization over variables in types. Variables to be generalized over
must be declared with their types in a variable block. For example:
variable
l : Level
n m : Nat

data Vec (A : Set l ) : Nat → Set l where


[] : Vec A 0
_::_ : A → Vec A n → Vec A (suc n)

Here the parameter l and the n in the type of _::_ are not bound explicitly, but since they are declared as generalizable
variables, bindings for them are inserted automatically. The level l is added as a parameter to the datatype and n is
added as an argument to _::_. The resulting declaration is
data Vec {l : Level} (A : Set l ) : Nat → Set l where
[] : Vec A 0
_::_ : {n : Nat} → A → Vec A n → Vec A (suc n)

See Placement of generalized bindings below for more details on where bindings are inserted.
Variables are generalized in top-level type signatures, module telescopes, and record and datatype parameter tele-
scopes.
Issues related to this feature are marked with generalize in the issue tracker.

3.14.2 Nested generalization

When generalizing a variable, any generalizable variables in its type are also generalized over. For instance, you can
declare A to be a type at some level l as
variable
A : Set l

3.14. Generalization of Declared Variables 79


Agda User Manual, Release 2.6.2

Now if A is mentioned in a type, the level l will also be generalized over:


-- id : {A.l : Level} {A : Set l } → A → A
id : A → A
id x = x

The nesting can be arbitrarily deep, so


variable
x : A

refl´ : x ≡ x
refl´ = refl

expands to
refl´ : {x.A.l : Level} {x.A : Set x.A.l } {x : x.A} → x ≡ x

See Naming of nested variables below for how the names are chosen.
Nested variables are not necessarily generalized over. In this example, if the universe level of A is fixed there is nothing
to generalize:
postulate
-- pure : {A : Set} {F : Set → Set} → A → F A
pure : {F : Set → Set} → A → F A

See Generalization over unsolved metavariables for more details.

Note: Nested generalized variables are local to each variable, so if you declare
variable
B : Set l

then A and B can still be generalized at different levels. For instance,


-- _$_ : {A.l : Level} {A : Set A.l } {B.l : Level} {B : Set B.l } → (A → B) → A → B
_$_ : (A → B) → A → B
f $ x = f x

Generalization over unsolved metavariables

Generalization over nested variables is implemented by creating a metavariable for each nested variable and generalize
over any such meta that is still unsolved after type checking. This is what makes the pure example from the previous
section work: the metavariable created for l is solved to level 0 and is thus not generalized over.
A typical case where this happens is when you have dependencies between different nested variables. For instance:
postulate
Con : Set

variable
Γ Δ Θ : Con

postulate
(continues on next page)

80 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


Sub : Con → Con → Set

idS : Sub Γ Γ
_∘_ : Sub Γ Δ → Sub Δ Θ → Sub Γ Θ

variable
𝛿 𝜎 𝛾 : Sub Γ Δ

postulate
assoc : 𝛿 ∘ (𝜎 ∘ 𝛾) ≡ (𝛿 ∘ 𝜎) ∘ 𝛾

In the type of assoc each substitution gets two nested variable metas for their contexts, but the type of _∘_ requires
the contexts of its arguments to match up, so some of these metavariables are solved. The resulting type is

assoc : {𝛿.Γ 𝛿.Δ : Con} {𝛿 : Sub 𝛿.Γ 𝛿.Δ} {𝜎.Δ : Con} {𝜎 : Sub 𝛿.Δ 𝜎.Δ}
{𝛾.Δ : Con} {𝛾 : Sub 𝜎.Δ 𝛾.Δ} → (𝛿 ∘ (𝜎 ∘ 𝛾)) ≡ ((𝛿 ∘ 𝜎) ∘ 𝛾)

where we can see from the names that 𝜎.Γ was unified with 𝛿.∆ and 𝛾.Γ with 𝜎.∆. In general, when unifying two
metavariables the “youngest” one is eliminated which is why 𝛿.∆ and 𝜎.∆ are the ones that remain in the type.
If a metavariable for a nested generalizable variable is partially solved, the left-over metas are generalized over. For
instance,

variable
xs : Vec A n

head : Vec A (suc n) → A


head (x :: _) = x

-- lemma : {xs.n.1 : Nat} {xs : Vec Nat (suc xs.n.1)} → head xs ≡ 1 → (0 < sum xs)
˓→≡ true

lemma : head xs ≡ 1 → (0 < sum xs) ≡ true

In the type of lemma a metavariable is created for the length of xs, which the application head xs refines to suc
_n, for some new metavariable _n. Since there are no further constraints on _n, it’s generalized over, creating the
type given in the comment. See Naming of nested variables below for how the name xs.n.1 is chosen.

Note: Only metavariables originating from nested variables are generalized over. An exception to this is in
variable blocks where all unsolved metas are turned into nested variables. This means writing

variable
A : Set _

is equivalent to A : Set l up to naming of the nested variable (see below).

Naming of nested variables

The general naming scheme for nested generalized variables is parentVar.nestedVar. So, in the case of the
identity function id : A → A expanding to

id : {A.l : Level} {A : Set l } → A → A

the name of the level variable is A.l since the name of the nested variable is l and its parent is the named variable A.
For multiple levels of nesting the parent can be another nested variable as in the refl´ case above

3.14. Generalization of Declared Variables 81


Agda User Manual, Release 2.6.2

refl´ : {x.A.l : Level} {x.A : Set x.A.l } {x : x.A} → x ≡ x

If a nested generalizable variable is solved with a term containing further metas, these are generalized over as explained
in the lemma example above. The names of the new variables are of the form parentName.i where parentName
is the name of the solved variable and i numbers the metas, starting from 1, in the order they appear in the solution.
If a variable comes from a free unsolved metavariable in a variable block (see this note), its name is chosen as
follows:
• If it is a labelled argument to a function, the label is used as the name,
• otherwise the name is its left-to-right index (starting at 1) in the list of unnamed variables in the type.
It is then given a hierarchical name based on the named variable whose type it occurs in. For example,

postulate
V : (A : Set) → Nat → Set
P : V A n → Set

variable
v : V _ _

postulate
thm : P v

Here there are two unnamed variables in the type of v, namely the two arguments to V. The first argument has the label
A in the definition of V, so this variable gets the name v.A. The second argument has no label and thus gets the name
v.2 since it is the second unnamed variable in the type of v.
If the variable comes from a partially instantiated nested variable the name of the metavariable is used unqualified.

Note: Currently it is not allowed to use hierarchical names when giving parameters to functions, see Issue #3208.

3.14.3 Placement of generalized bindings

The following rules are used to place generalized variables:


• Generalized variables are placed at the front of the type signature or telescope.
• Variables mentioned eariler are placed before variables mentioned later, where nested variables count as being
mentioned together with their parent.

Note: This means that an implicitly quantified variable cannot depend on an explicitly quantified one. See Issue
#3352 for the feature request to lift this restriction.

Indexed datatypes

When generalizing datatype parameters and indicies a variable is turned into an index if it is only mentioned in indices
and into a parameter otherwise. For instance,

data All (P : A → Set) : Vec A n → Set where


[] : All P []
_::_ : P x → All P xs → All P (x :: xs)

82 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Here A is generalized as a parameter and n as an index. That is, the resulting signature is

data All {A : Set} (P : A → Set) : {n : Nat} → Vec A n → Set where

3.14.4 Instance and irrelevant variables

Generalized variables are introduced as implicit arguments by default, but this can be changed to instance arguments
or irrelevant arguments by annotating the declaration of the variable:

record Eq (A : Set) : Set where


field eq : A → A → Bool

variable
{{EqA}} : Eq A -- generalized as an instance argument
.ignore : A -- generalized as an irrelevant (implicit) argument

Variables are never generalized as explicit arguments.

3.14.5 Importing and exporting variables

Generalizable variables are treated in the same way as other declared symbols (functions, datatypes, etc) and use the
same mechanisms for importing and exporting between modules. This means that unless marked private they are
exported from a module.

3.14.6 Interaction

When developing types interactively, generalizable variables can be used in holes if they have already been generalized,
but it is not possible to introduce new generalizations interactively. For instance,

works : (A → B) → Vec A n → Vec B {!n!}


fails : (A → B) → Vec A {!n!} → Vec B {!n!}

In works you can give n in the hole, since a binding for n has been introduced by its occurrence in the argument
vector. In fails on the other hand, there is no reference to n so neither hole can be filled interactively.

3.14.7 Modalities

One can give a modality when declaring a generalizable variable:

variable
@0 o : Nat

In the generalization process generalizable variables get the modality that they are declared with, whereas other vari-
ables always get the default modality.

3.15 Guarded Cubical

Note: This is a stub.

3.15. Guarded Cubical 83


Agda User Manual, Release 2.6.2

Cubical Agda is extended with Nakano’s later modality and guarded recursion based on Ticked Cubical Type Theory
[2]. For its usage, see [1] or the example.

3.15.1 References

[1] Niccolò Veltri and Andrea Vezzosi. “Formalizing pi-calculus in guarded cubical Agda.” In CPP’20. ACM, New
York, NY, USA, 2020.
[2] Rasmus Ejlers Møgelberg and Niccolò Veltri. “Bisimulation as path type for guarded recursive types.” In POPL’19,
2019.

3.16 Implicit Arguments

It is possible to omit terms that the type checker can figure out for itself, replacing them by _. If the type checker
cannot infer the value of an _ it will report an error. For instance, for the polymorphic identity function

id : (A : Set) → A → A

the first argument can be inferred from the type of the second argument, so we might write id _ zero for the
application of the identity function to zero.
We can even write this function application without the first argument. In that case we declare an implicit function
space:

id : {A : Set} → A → A

and then we can use the notation id zero.


Another example:

_==_ : {A : Set} → A → A → Set


subst : {A : Set} (C : A → Set) {x y : A} → x == y → C x → C y

Note how the first argument to _==_ is left implicit. Similarly, we may leave out the implicit arguments A, x, and
y in an application of subst. To give an implicit argument explicitly, enclose it in curly braces. The following two
expressions are equivalent:

x1 = subst C eq cx
x2 = subst {_} C {_} {_} eq cx

It is worth noting that implicit arguments are also inserted at the end of an application, if it is required by the type. For
example, in the following, y1 and y2 are equivalent.

y1 : a == b → C a → C b
y1 = subst C

y2 : a == b → C a → C b
y2 = subst C {_} {_}

Implicit arguments are inserted eagerly in left-hand sides so y3 and y4 are equivalent. An exception is when no type
signature is given, in which case no implicit argument insertion takes place. Thus in the definition of y5 the only
implicit is the A argument of subst.

84 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

y3 : {x y : A} → x == y → C x → C y
y3 = subst C

y4 : {x y : A} → x == y → C x → C y
y4 {x} {y} = subst C {_} {_}

y5 = subst C

It is also possible to write lambda abstractions with implicit arguments. For example, given id : (A : Set) →
A → A, we can define the identity function with implicit type argument as
id’ = 𝜆 {A} → id A

Implicit arguments can also be referred to by name, so if we want to give the expression e explicitly for y without
giving a value for x we can write
subst C {y = e} eq cx

In rare circumstances it can be useful to separate the name used to give an argument by name from the name of the
bound variable, for instance if the desired name shadows an existing name. To do this you write
id2 : {A = X : Set} → X → X -- name of bound variable is X
id2 x = x

use-id2 : (Y : Set) → Y → Y
use-id2 Y = id2 {A = Y} -- but the label is A

Labeled bindings must appear by themselves when typed, so the type Set needs to be repeated in this example:
const : {A = X : Set} {B = Y : Set} → A → B → A
const x y = x

When constructing implicit function spaces the implicit argument can be omitted, so both expressions below are valid
expressions of type {A : Set} → A → A:
z1 = 𝜆 {A} x → x
z2 = 𝜆 x → x

The ∀ (or forall) syntax for function types also has implicit variants:
¬ : (∀ {x : A} → B) is-the-same-as ({x : A} → B)
­ : (∀ {x} → B) is-the-same-as ({x : _} → B)
® : (∀ {x y} → B) is-the-same-as (∀ {x} → ∀ {y} → B)

In very special situations it makes sense to declare unnamed hidden arguments {A} → B. In the following example,
the hidden argument to scons of type zero ≤ zero can be solved by 𝜂-expansion, since this type reduces to ⊤.
data ⊥ : Set where

_≤_ : Nat → Nat → Set


zero ≤ _ = ⊤
suc m ≤ zero = ⊥
suc m ≤ suc n = m ≤ n

data SList (bound : Nat) : Set where


[] : SList bound
scons : (head : Nat) → {head ≤ bound} → (tail : SList head) → SList bound
(continues on next page)

3.16. Implicit Arguments 85


Agda User Manual, Release 2.6.2

(continued from previous page)

example : SList zero


example = scons zero []

There are no restrictions on when a function space can be implicit. Internally, explicit and implicit function spaces are
treated in the same way. This means that there are no guarantees that implicit arguments will be solved. When there
are unsolved implicit arguments the type checker will give an error message indicating which application contains
the unsolved arguments. The reason for this liberal approach to implicit arguments is that limiting the use of implicit
argument to the cases where we guarantee that they are solved rules out many useful cases in practice.

3.16.1 Tactic arguments

You can declare tactics to be used to solve a particular implicit argument using the @(tactic t) attribute, where t
: Term → TC ⊤. For instance:

clever-search : Term → TC ⊤
clever-search hole = unify hole (lit (nat 17))

the-best-number : {@(tactic clever-search) n : Nat} → Nat


the-best-number {n} = n

check : the-best-number ≡ 17
check = refl

The tactic can be an arbitrary term of the right type and may depend on previous arguments to the function:

default : {A : Set} → A → Term → TC ⊤


default x hole = bindTC (quoteTC x) (unify hole)

search : (depth : Nat) → Term → TC ⊤

example : {@(tactic default 10) depth : Nat}


{@(tactic search depth) proof : Proof} →
Goal

3.16.2 Metavariables

3.16.3 Unification

3.17 Instance Arguments

• Usage
– Defining type classes
– Declaring instances
– Restricting instance search
– Examples
• Instance resolution

86 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Instance arguments are a special kind of implicit arguments that get solved by a special instance resolution algo-
rithm, rather than by the unification algorithm used for normal implicit arguments. Instance arguments are the Agda
equivalent of Haskell type class constraints and can be used for many of the same purposes.
An instance argument will be resolved if its type is a named type (i.e. a data type or record type) or a variable type
(i.e. a previously bound variable of type Set l ), and a unique instance of the required type can be built from declared
instances and the current context.

3.17.1 Usage

Instance arguments are enclosed in double curly braces {{ }}, e.g. {{x : T}}. Alternatively they can be
enclosed, with proper spacing, e.g. PDF TODO x : T PDF TODO, in the unicode braces PDF TODO
PDF TODO (U+2983 and U+2984, which can be typed as \{{ and \}} in the Emacs mode).
For instance, given a function _==_
_==_ : {A : Set} {{eqA : Eq A}} → A → A → Bool

for some suitable type Eq, you might define


elem : {A : Set} {{eqA : Eq A}} → A → List A → Bool
elem x (y :: xs) = x == y || elem x xs
elem x [] = false

Here the instance argument to _==_ is solved by the corresponding argument to elem. Just like ordinary implicit
arguments, instance arguments can be given explicitly. The above definition is equivalent to
elem : {A : Set} {{eqA : Eq A}} → A → List A → Bool
elem {{eqA}} x (y :: xs) = _==_ {{eqA}} x y || elem {{eqA}} x xs
elem x [] = false

A very useful function that exploits this is the function it which lets you apply instance resolution to solve an arbitrary
goal:
it : ∀ {a} {A : Set a} → {{A}} → A
it {{x}} = x

As the last example shows, the name of the instance argument can be omitted in the type signature:
_==_ : {A : Set} → {{Eq A}} → A → A → Bool

Defining type classes

The type of an instance argument should have the form {Γ} → C vs, where C is a postulated name, a bound
variable, or the name of a data or record type, and {Γ} denotes an arbitrary number of implicit or instance arguments
(see Dependent instances below for an example where {Γ} is non-empty).
Instances with explicit arguments are also accepted but will not be considered as instances because the value of the
explicit arguments cannot be derived automatically. Having such an instance has no effect and thus raises a warning.
Instance arguments whose types end in any other type are currently also accepted but cannot be resolved by instance
search, so they must be given by hand. For this reason it is not recommended to use such instance arguments. Doing
so will also raise a warning.
Other than that there are no requirements on the type of an instance argument. In particular, there is no special
declaration to say that a type is a “type class”. Instead, Haskell-style type classes are usually defined as record types.
For instance,

3.17. Instance Arguments 87


Agda User Manual, Release 2.6.2

record Monoid {a} (A : Set a) : Set a where


field
mempty : A
_<>_ : A → A → A

In order to make the fields of the record available as functions taking instance arguments you can use the special
module application

open Monoid {{...}} public

This will bring into scope

mempty : ∀ {a} {A : Set a} → {{Monoid A}} → A


_<>_ : ∀ {a} {A : Set a} → {{Monoid A}} → A → A → A

Superclass dependencies can be implemented using Instance fields.


See Module application and Record modules for details about how the module application is desugared. If defined by
hand, mempty would be

mempty : ∀ {a} {A : Set a} → {{Monoid A}} → A


mempty {{mon}} = Monoid.mempty mon

Although record types are a natural fit for Haskell-style type classes, you can use instance arguments with data types
to good effect. See the Examples below.

Declaring instances

As seen above, instance arguments in the context are available when solving instance arguments, but you also need
to be able to define top-level instances for concrete types. This is done using the instance keyword, which starts
a block in which each definition is marked as an instance available for instance resolution. For example, an instance
Monoid (List A) can be defined as

instance
ListMonoid : ∀ {a} {A : Set a} → Monoid (List A)
ListMonoid = record { mempty = []; _<>_ = _++_ }

Or equivalently, using copatterns:

instance
ListMonoid : ∀ {a} {A : Set a} → Monoid (List A)
mempty {{ListMonoid}} = []
_<>_ {{ListMonoid}} xs ys = xs ++ ys

Top-level instances must target a named type (Monoid in this case), and cannot be declared for types in the context.
You can define local instances in let-expressions in the same way as a top-level instance. For example:

mconcat : ∀ {a} {A : Set a} → {{Monoid A}} → List A → A


mconcat [] = mempty
mconcat (x :: xs) = x <> mconcat xs

sum : List Nat → Nat


sum xs =
let instance
NatMonoid : Monoid Nat
(continues on next page)

88 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


NatMonoid = record { mempty = 0; _<>_ = _+_ }
in mconcat xs

Instances can have instance arguments themselves, which will be filled in recursively during instance resolution. For
instance,

record Eq {a} (A : Set a) : Set a where


field
_==_ : A → A → Bool

open Eq {{...}} public

instance
eqList : ∀ {a} {A : Set a} → {{Eq A}} → Eq (List A)
_==_ {{eqList}} [] [] = true
_==_ {{eqList}} (x :: xs) (y :: ys) = x == y && xs == ys
_==_ {{eqList}} _ _ = false

eqNat : Eq Nat
_==_ {{eqNat}} = natEquals

ex : Bool
ex = (1 :: 2 :: 3 :: []) == (1 :: 2 :: []) -- false

Note the two calls to _==_ in the right-hand side of the second clause. The first uses the Eq A instance and the second
uses a recursive call to eqList. In the example ex, instance resolution, needing a value of type Eq (List Nat),
will try to use the eqList instance and find that it needs an instance argument of type Eq Nat, it will then solve
that with eqNat and return the solution eqList {{eqNat}}.

Note: At the moment there is no termination check on instances, so it is possible to construct non-sensical in-
stances like loop : ∀ {a} {A : Set a} → {{Eq A}} → Eq A. To prevent looping in cases like this,
the search depth of instance search is limited, and once the maximum depth is reached, a type error will be thrown.
You can set the maximum depth using the --instance-search-depth flag.

Restricting instance search

To restrict an instance to the current module, you can mark it as private. For instance,

record Default (A : Set) : Set where


field default : A

open Default {{...}} public

module M where

private
instance
defaultNat : Default Nat
defaultNat .default = 6

test1 : Nat
test1 = default

(continues on next page)

3.17. Instance Arguments 89


Agda User Manual, Release 2.6.2

(continued from previous page)


_ : test1 ≡ 6
_ = refl

open M

instance
defaultNat : Default Nat
defaultNat .default = 42

test2 : Nat
test2 = default

_ : test2 ≡ 42
_ = refl

Constructor instances

Although instance arguments are most commonly used for record types, mimicking Haskell-style type classes, they
can also be used with data types. In this case you often want the constructors to be instances, which is achieved by
declaring them inside an instance block. Constructors can only be declared as instances if all their arguments are
implicit or instance arguments. See Instance resolution below for the details.
A simple example of a constructor that can be made an instance is the reflexivity constructor of the equality type:

data _≡_ {a} {A : Set a} (x : A) : A → Set a where


instance refl : x ≡ x

This allows trivial equality proofs to be inferred by instance resolution, which can make working with functions that
have preconditions less of a burden. As an example, here is how one could use this to define a function that takes a
natural number and gives back a Fin n (the type of naturals smaller than n):

data Fin : Nat → Set where


zero : ∀ {n} → Fin (suc n)
suc : ∀ {n} → Fin n → Fin (suc n)

mkFin : ∀ {n} (m : Nat) → {{suc m - n ≡ 0}} → Fin n


mkFin {zero} m {{}}
mkFin {suc n} zero = zero
mkFin {suc n} (suc m) = suc (mkFin m)

five : Fin 6
five = mkFin 5 -- OK

In the first clause of mkFin we use an absurd pattern to discharge the impossible assumption suc m ≡ 0. See the
next section for another example of constructor instances.
Record fields can also be declared instances, with the effect that the corresponding projection function is considered a
top-level instance.

Overlapping instances

By default, Agda does not allow overlapping instances. Two instances are defined to overlap if they could both solve
the instance goal when given appropriate solutions for their recursive (instance) arguments.

90 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

For example, in code below, the instances zero and suc overlap for the goal ex1 , because either one of them can be
used to solve the goal when given appropriate arguments, hence instance search fails.

infix 4 _∈_
data _∈_ {A : Set} (x : A) : List A → Set where
instance
zero : ∀ {xs} → x ∈ x :: xs
suc : ∀ {y xs} → {{x ∈ xs}} → x ∈ y :: xs

ex1 : 1 ∈ 1 :: 2 :: 3 :: 4 :: []
ex1 = it -- overlapping instances

Overlapping instances can be enabled via the --overlapping-instances flag. Be aware that enabling this flag
might lead to an exponential slowdown in instance resolution and possibly (apparent) looping behaviour.

Examples

Dependent instances

Consider a variant on the Eq class where the equality function produces a proof in the case the arguments are equal:

record Eq {a} (A : Set a) : Set a where


field
_==_ : (x y : A) → Maybe (x ≡ y)

open Eq {{...}} public

A simple boolean-valued equality function is problematic for types with dependencies, like the Σ-type

data Σ {a b} (A : Set a) (B : A → Set b) : Set (a ⊔ b) where


_,_ : (x : A) → B x → Σ A B

since given two pairs x , y and x1 , y1 , the types of the second components y and y1 can be completely different
and not admit an equality test. Only when x and x1 are really equal can we hope to compare y and y1 . Having the
equality function return a proof means that we are guaranteed that when x and x1 compare equal, they really are equal,
and comparing y and y1 makes sense.
An Eq instance for Σ can be defined as follows:

instance
eqΣ : ∀ {a b} {A : Set a} {B : A → Set b} → {{Eq A}} → {{∀ {x} → Eq (B x)}} → Eq
˓→(Σ A B)

_==_ {{eqΣ}} (x , y) (x1 , y1 ) with x == x1


_==_ {{eqΣ}} (x , y) (x1 , y1 ) | nothing = nothing
_==_ {{eqΣ}} (x , y) (.x , y1 ) | just refl with y == y1
_==_ {{eqΣ}} (x , y) (.x , y1 ) | just refl | nothing = nothing
_==_ {{eqΣ}} (x , y) (.x , .y) | just refl | just refl = just refl

Note that the instance argument for B states that there should be an Eq instance for B x, for any x : A. The
argument x must be implicit, indicating that it needs to be inferred by unification whenever the B instance is used. See
Instance resolution below for more details.

3.17.2 Instance resolution

Given a goal that should be solved using instance resolution we proceed in the following four stages:

3.17. Instance Arguments 91


Agda User Manual, Release 2.6.2

Verify the goal First we check that the goal type has the right shape to be solved by instance resolution. It should
be of the form {Γ} → C vs, where the target type C is a variable from the context or the name of a data
or record type, and {Γ} denotes a telescope of implicit or instance arguments. If this is not the case instance
resolution fails with an error message1 .
Find candidates In the second stage we compute a set of candidates. Let-bound variables and top-level definitions in
scope are candidates if they are defined in an instance block. Lambda-bound variables, i.e. variables bound
in lambdas, function types, left-hand sides, or module parameters, are candidates if they are bound as instance
arguments using {{ }}. Only candidates of type {∆} → C us, where C is the target type computed in the
previous stage and {∆} only contains implicit or instance arguments, are considered.
Check the candidates We attempt to use each candidate in turn to build an instance of the goal type {Γ} → C vs.
First we extend the current context by {Γ}. Then, given a candidate c : {∆} → A we generate fresh
metavariables 𝛼s : {∆} for the arguments of c, with ordinary metavariables for implicit arguments, and
instance metavariables, solved by a recursive call to instance resolution, for instance arguments.
Next we unify A[∆ := 𝛼s] with C vs and apply instance resolution to the instance metavariables in 𝛼s.
Both unification and instance resolution have three possible outcomes: yes, no, or maybe. In case we get a no
answer from any of them, the current candidate is discarded, otherwise we return the potential solution 𝜆 {Γ}
→ c 𝛼s.
Compute the result From the previous stage we get a list of potential solutions. If the list is empty we fail with an
error saying that no instance for C vs could be found (no). If there is a single solution we use it to solve the
goal (yes), and if there are multiple solutions we check if they are all equal. If they are, we solve the goal with
one of them (yes), but if they are not, we postpone instance resolution (maybe), hoping that some of the maybes
will turn into nos once we know more about the involved metavariables.
If there are left-over instance problems at the end of type checking, the corresponding metavariables are printed
in the Emacs status buffer together with their types and source location. The candidates that gave rise to potential
solutions can be printed with the show constraints command (C-c C-=).

3.18 Irrelevance

Since version 2.2.8 Agda supports irrelevancy annotations. The general rule is that anything prepended by a dot (.) is
marked irrelevant, which means that it will only be typechecked but never evaluated.

Note: This section is about compile-time irrelevance. See Run-time Irrelevance for the section on run-time irrele-
vance.

3.18.1 Motivating example

One intended use case of irrelevance is data structures with embedded proofs, like sorted lists.

data _≤_ : Nat → Nat → Set where


zero≤ : {n : Nat} → zero ≤ n
suc≤suc : {m n : Nat} → m ≤ n → suc m ≤ suc n

postulate
p1 : 0 ≤ 1
p2 : 0 ≤ 1

(continues on next page)


1 Instance goal verification is buggy at the moment. See issue #1322.

92 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


module No-Irrelevance where
data SList (bound : Nat) : Set where
[] : SList bound
scons : (head : Nat)
→ (head ≤ bound)
→ (tail : SList head)
→ SList bound

Usually, when we define datatypes with embedded proofs we are forced to reason about the values of these proofs.
For example, suppose we have two lists l1 and l2 with the same elements but different proofs:
l1 : SList 1
l1 = scons 0 p1 []

l2 : SList 1
l2 = scons 0 p2 []

Now suppose we want to prove that l1 and l2 are equal:


l1 ≡l2 : l1 ≡ l2
l1 ≡l2 = refl

It’s not so easy! Agda gives us an error:


p1 != p2 of type 0 ≤ 1
when checking that the expression refl has type l1 ≡ l2

We can’t show that l1 ≡ l2 by refl when p1 and p2 are relevant. Instead, we need to reason about proofs of 0 ≤
1.
postulate
proof-equality : p1 ≡ p2

Now we can prove l1 ≡ l2 by rewriting with this equality:


l1 ≡l2 : l1 ≡ l2
l1 ≡l2 rewrite proof-equality = refl

Reasoning about equality of proofs becomes annoying quickly. We would like to avoid this kind of reasoning about
proofs here - in this case we only care that a proof of head ≤ bound exists, i.e. any proof suffices. We can use
irrelevance annotations to tell Agda we don’t care about the values of the proofs:
data SList (bound : Nat) : Set where
[] : SList bound
scons : (head : Nat)
→ .(head ≤ bound) -- note the dot!
→ (tail : SList head)
→ SList bound

The effect of the irrelevant type in the signature of scons is that scons’s second argument is never inspected after Agda
has ensured that it has the right type. The type-checker ignores irrelevant arguments when checking equality, so two
lists can be equal even if they contain different proofs:
l1 : SList 1
l1 = scons 0 p1 []

(continues on next page)

3.18. Irrelevance 93
Agda User Manual, Release 2.6.2

(continued from previous page)


l2 : SList 1
l2 = scons 0 p2 []

l1 ≡l2 : l1 ≡ l2
l1 ≡l2 = refl

3.18.2 Irrelevant function types

For starters, consider irrelevant non-dependent function types:

f : .A → B

This type implies that f does not depend computationally on its argument.

What can be done to irrelevant arguments

Example 1. We can prove that two applications of an unknown irrelevant function to two different arguments are
equal.

-- an unknown function that does not use its second argument


postulate
f : {A B : Set} -> A -> .B -> A

-- the second argument is irrelevant for equality


proofIrr : {A : Set}{x y z : A} -> f x y ≡ f x z
proofIrr = refl

Example 2. We can use irrelevant arguments as arguments to other irrelevant functions.

id : {A B : Set} -> (.A -> B) -> .A -> B


id g x = g x

Example 3. We can match on an irrelevant argument of an empty type with an absurd pattern ().

data ⊥ : Set where

zero-not-one : .(0 ≡ 1) → ⊥
zero-not-one ()

What can’t be done to irrelevant arguments

Example 1. You can’t use an irrelevant value in a non-irrelevant context.

bad-plus : Nat → .Nat → Nat


bad-plus n m = m + n

Variable m is declared irrelevant, so it cannot be used here


when checking that the expression m has type Nat

Example 2. You can’t declare the function’s return type as irrelevant.

94 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

bad : Nat → .Nat


bad n = 1

Invalid dotted expression


when checking that the expression .Nat has type Set _47

Example 3. You can’t pattern match on an irrelevant value.

badMatching : Nat → .Nat → Nat


badMatching n zero = n
badMatching n (suc m) = n

Cannot pattern match against irrelevant argument of type Nat


when checking that the pattern zero has type Nat

Example 4. We also can’t match on an irrelevant record (see Record Types).

record Σ (A : Set) (B : A → Set) : Set where


constructor _,_
field
fst : A
snd : B fst

irrElim : {A : Set} {B : A → Set} → .(Σ A B) → _


irrElim (a , b) = ?

Cannot pattern match against irrelevant argument of type Σ A B


when checking that the pattern a , b has type Σ A B

If this were allowed, b would have type B a but this type is not even well-formed because a is irrelevant!

3.18.3 Irrelevant declarations

Postulates and functions can be marked as irrelevant by prefixing the name with a dot when the name is declared.
Irrelevant definitions can only be used as arguments of functions of an irrelevant function type .A → B.
Examples:

.irrFunction : Nat → Nat


irrFunction zero = zero
irrFunction (suc n) = suc (suc (irrFunction n))

postulate
.assume-false : (A : Set) → A

An important example is the irrelevance axiom irrAx:

postulate
.irrAx : ∀ {l } {A : Set l } -> .A -> A

This axiom is not provable inside Agda, but it is often very useful when working with irrelevance.

3.18. Irrelevance 95
Agda User Manual, Release 2.6.2

3.18.4 Irrelevant record fields

Record fields (see Record Types) can be marked as irrelevant by prefixing their name with a dot in the definition of the
record type. Projections for irrelevant fields are only created if option --irrelevant-projections is supplied
(since Agda > 2.5.4).
Example 1. A record type containing pairs of numbers satisfying certain properties.

record InterestingNumbers : Set where


field
n : Nat
m : Nat
.prop1 : n + m ≡ n * m + 2
.prop2 : suc m ≤ n

Example 2. For any type A, we can define a ‘squashed’ version Squash A where all elements are equal.

record Squash (A : Set) : Set where


constructor squash
field
.proof : A

open Squash

.unsquash : ∀ {A} → Squash A → A


unsquash x = proof x

Example 3. We can define the subset of x : A satisfying P x with irrelevant membership certificates.

record Subset (A : Set) (P : A -> Set) : Set where


constructor _#_
field
elem : A
.certificate : P elem

.certificate : {A : Set}{P : A -> Set} -> (x : Subset A P) -> P (Subset.elem x)


certificate (a # p) = irrAx p

3.18.5 Dependent irrelevant function types

Just like non-dependent functions, we can also make dependent functions irrelevant. The basic syntax is as in the
following examples:

f : .(x y : A) → B
f : .{x y z : A} → B
f : .(xs {ys zs} : A) → B
f : ∀ x .y → B
f : ∀ x .{y} {z} .v → B
f : .{{x : A}} → B

The declaration

f : .(x : A) → B[x]
f x = t[x]

requires that x is irrelevant both in t[x] and in B[x]. This is possible if, for instance, B[x] = C x, with C : .A
→ Set.

96 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Dependent irrelevance allows us to define the eliminator for the Squash type:

elim-Squash : {A : Set} (P : Squash A → Set)


(ih : .(a : A) → P (squash a)) →
(a− : Squash A) → P a−
elim-Squash P ih (squash a) = ih a

Note that this would not type-check with (ih : (a : A) → P (squash a)).

3.18.6 Irrelevant instance arguments

Contrary to normal instance arguments, irrelevant instance arguments (see Instance Arguments) are not required to
have a unique solution.

record ⊤ : Set where


instance constructor tt

NonZero : Nat → Set


NonZero zero = ⊥
NonZero (suc _) = ⊤

pred´ : (n : Nat) .{{_ : NonZero n}} → Nat


pred´ zero {{}}
pred´ (suc n) = n

find-nonzero : (n : Nat) {{x y : NonZero n}} → Nat


find-nonzero n = pred´ n

3.18.7 Subtyping of irrelevant function spaces

Normally, if f : .(x : A) → B then we have 𝜆 x → f x : (x : A) → B but not f : (x :


A) → B. When the option --subtyping is enabled, Agda will make use of the subtyping rule .(x : A) →
B <: (x : A) → B, so there is no need for eta-expanding the function f.

3.19 Lambda Abstraction

3.19.1 Pattern matching lambda

Anonymous pattern matching functions can be defined using one of the two following syntaxes:

\ { p11 .. p1n -> e1 ; ... ; pm1 .. pmn -> em }

\ where
p11 .. p1n -> e1
...
pm1 .. pmn -> em

(where, as usual, \ and -> can be replaced by 𝜆 and →). Note that the where keyword introduces an indented block
of clauses; if there is only one clause then it may be used inline.
Internally this is translated into a function definition of the following form:

3.19. Lambda Abstraction 97


Agda User Manual, Release 2.6.2

extlam p11 .. p1n = e1


...
extlam pm1 .. pmn = em

where extlam is a fresh name. This means that anonymous pattern matching functions are generative. For instance,
refl will not be accepted as an inhabitant of the type

(𝜆 { true → true ; false → false }) ==


(𝜆 { true → true ; false → false })

because this is equivalent to extlam1 ≡ extlam2 for some distinct fresh names extlam1 and extlam2. Cur-
rently the where and with constructions are not allowed in (the top-level clauses of) anonymous pattern matching
functions.
Examples:

and : Bool → Bool → Bool


and = 𝜆 { true x → x ; false _ → false }

xor : Bool → Bool → Bool


xor = 𝜆 { true true → false
; false false → false
; _ _ → true
}

eq : Bool → Bool → Bool


eq = 𝜆 where
true true → true
false false → true
_ _ → false

fst : {A : Set} {B : A → Set} → Σ A B → A


fst = 𝜆 { (a , b) → a }

snd : {A : Set} {B : A → Set} (p : Σ A B) → B (fst p)


snd = 𝜆 { (a , b) → b }

swap : {A B : Set} → Σ A (𝜆 _ → B) → Σ B (𝜆 _ → A)
swap = 𝜆 where (a , b) → (b , a)

Regular pattern-matching lambdas are treated as non-erased function definitions. One can make a pattern-matching
lambda erased by writing @0 or @erased after the lambda:

@0 _ : @0 Set → Set
_ = 𝜆 @0 { A → A }

@0 _ : @0 Set → Set
_ = 𝜆 @erased where
A → A

3.20 Local Definitions: let and where

There are two ways of declaring local definitions in Agda:


• let-expressions

98 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• where-blocks

3.20.1 let-expressions

A let-expression defines an abbreviation. In other words, the expression that we define in a let-expression can neither
be recursive, nor can let bound functions be defined by pattern matching.
Example:

f : Nat
f = let h : Nat → Nat
h m = suc (suc m)
in h zero + h (suc zero)

let-expressions have the general form

let f1 : A11 → ... → A1𝑛 → A1


f1 x1 ... x𝑛 = e1
...
f𝑚 : A𝑚1 → ... → A𝑚𝑘 → A𝑚
f𝑚 x1 ... x𝑘 = e𝑚
in e’

where previous definitions are in scope in later definitions. The type signatures can be left out if Agda can infer
them. After type-checking, the meaning of this is simply the substitution e’[f1 := 𝜆 x1 ... x𝑛 → e;
...; f𝑚 := 𝜆 x1 ... x𝑘 → e𝑚 ]. Since Agda substitutes away let-bindings, they do not show up in
terms Agda prints, nor in the goal display in interactive mode.

Let binding record patterns

For a record

record R : Set where


constructor c
field
f : X
g : Y
h : Z

a let expression of the form

let (c x y z) = t
in u

will be translated internally to as

let x = f t
y = g t
z = h t
in u

This is not allowed if R is declared coinductive.

3.20. Local Definitions: let and where 99


Agda User Manual, Release 2.6.2

3.20.2 where-blocks

where-blocks are much more powerful than let-expressions, as they support arbitrary local definitions. A where can
be attached to any function clause.
where-blocks have the general form

clause
where
decls

or

clause
module M where
decls

A simple instance is

g ps = e
where
f : A1 → ... → A𝑛 → A
f p11 ... p1𝑛 = e1
...
...
f p𝑚1 ... p𝑚𝑛 = e𝑚

Here, the p𝑖𝑗 are patterns of the corresponding types and e𝑖 is an expression that can contain occurrences of f.
Functions defined with a where-expression must follow the rules for general definitions by pattern matching.
Example:

reverse : {A : Set} → List A → List A


reverse {A} xs = rev-append xs []
where
rev-append : List A → List A → List A
rev-append [] ys = ys
rev-append (x :: xs) ys = rev-append xs (x :: ys)

Variable scope

The pattern variables of the parent clause of the where-block are in scope; in the previous example, these are A and
xs. The variables bound by the type signature of the parent clause are not in scope. This is why we added the hidden
binder {A}.

Scope of the local declarations

The where-definitions are not visible outside of the clause that owns these definitions (the parent clause). If the
where-block is given a name (form module M where), then the definitions are available as qualified by M, since
module M is visible even outside of the parent clause. The special form of an anonymous module (module _
where) makes the definitions visible outside of the parent clause without qualification.
If the parent function of a named where-block (form module M where) is private, then module M is also
private. However, the declarations inside M are not private unless declared so explicitly. Thus, the following
example scope checks fine:

100 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

module Parent1 where


private
parent = local
module Private where
local = Set
module Public = Private

test1 = Parent1 .Public.local

Likewise, a private declaration for a parent function does not affect the privacy of local functions defined under a
module _ where-block:
module Parent2 where
private
parent = local
module _ where
local = Set

test2 = Parent2 .local

They can be declared private explicitly, though:


module Parent3 where
parent = local
module _ where
private
local = Set

Now, Parent3 .local is not in scope.


A private declaration for the parent of an ordinary where-block has no effect on the local definitions, of course.
They are not even in scope.

3.20.3 Proving properties

Sometimes one needs to refer to local definitions in proofs about the parent function. In this case, the module · · ·
where variant is preferable.
reverse : {A : Set} → List A → List A
reverse {A} xs = rev-append xs []
module Rev where
rev-append : List A → List A → List A
rev-append [] ys = ys
rev-append (x :: xs) ys = rev-append xs (x :: ys)

This gives us access to the local function as


Rev.rev-append : {A : Set} (xs : List A) → List A → List A → List A

Alternatively, we can define local functions as private to the module we are working in; hence, they will not be visible
in any module that imports this module but it will allow us to prove some properties about them.
private
rev-append : {A : Set} → List A → List A → List A
rev-append [] ys = ys
rev-append (x :: xs) ys = rev-append xs (x :: ys)
(continues on next page)

3.20. Local Definitions: let and where 101


Agda User Manual, Release 2.6.2

(continued from previous page)

reverse' : {A : Set} → List A → List A


reverse' xs = rev-append xs []

3.20.4 More Examples (for Beginners)

Using a let-expression:

tw-map : {A : Set} → List A → List (List A)


tw-map {A} xs = let twice : List A → List A
twice xs = xs ++ xs
in map (\ x → twice [ x ]) xs

Same definition but with less type information:

tw-map' : {A : Set} → List A → List (List A)


tw-map' {A} xs = let twice : _
twice xs = xs ++ xs
in map (\ x → twice [ x ]) xs

Same definition but with a where-expression

tw-map'' : {A : Set} → List A → List (List A)


tw-map'' {A} xs = map (\ x → twice [ x ]) xs
where twice : List A → List A
twice xs = xs ++ xs

Even less type information using let:

g : Nat → List Nat


g zero = [ zero ]
g (suc n) = let sing = [ suc n ]
in sing ++ g n

Same definition using where:

g' : Nat → List Nat


g' zero = [ zero ]
g' (suc n) = sing ++ g' n
where sing = [ suc n ]

More than one definition in a let:

h : Nat → Nat
h n = let add2 : Nat
add2 = suc (suc n)

twice : Nat → Nat


twice m = m * m

in twice add2

More than one definition in a where:

102 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

fibfact : Nat → Nat


fibfact n = fib n + fact n
where fib : Nat → Nat
fib zero = suc zero
fib (suc zero) = suc zero
fib (suc (suc n)) = fib (suc n) + fib n

fact : Nat → Nat


fact zero = suc zero
fact (suc n) = suc n * fact n

Combining let and where:

k : Nat → Nat
k n = let aux : Nat → Nat
aux m = pred (h m) + fibfact m
in aux (pred n)
where pred : Nat → Nat
pred zero = zero
pred (suc m) = m

3.21 Lexical Structure

Agda code is written in UTF-8 encoded plain text files with the extension .agda. Most unicode characters can be
used in identifiers and whitespace is important, see Names and Layout below.

3.21.1 Tokens

Keywords and special symbols

Most non-whitespace unicode can be used as part of an Agda name, but there are two kinds of exceptions:
special symbols Characters with special meaning that cannot appear at all in a name. These are .;{}()@".
keywords Reserved words that cannot appear as a name part, but can appear in a name together with other characters.
= | -> → : ? \ 𝜆 ∀ .. ... abstract constructor data do eta-equality field forall hiding
import in inductive infix infixl infixr instance interleaved let macro module
mutual no-eta-equality open overlap pattern postulate primitive private public
quote quoteContext quoteGoal quoteTerm record renaming rewrite Set syntax tactic un-
quote unquoteDecl unquoteDef using variable where with
The Set keyword can appear with a natural number suffix, optionally subscripted (see Sort System). For in-
stance Set42 and Set42 are both keywords.

Names

A qualified name is a non-empty sequence of names separated by dots (.). A name is an alternating sequence of
name parts and underscores (_), containing at least one name part. A name part is a non-empty sequence of unicode
characters, excluding whitespace, _, and special symbols. A name part cannot be one of the keywords above, and
cannot start with a single quote, ' (which are used for character literals, see Literals below).
Examples

3.21. Lexical Structure 103


Agda User Manual, Release 2.6.2

• Valid: data?, ::, if_then_else_, 0b, _⊢_∈_, x=y


• Invalid: data_?, foo__bar, _, a;b, [_.._]
The underscores in a name indicate where the arguments go when the name is used as an operator. For instance, the
application _+_ 1 2 can be written as 1 + 2. See Mixfix Operators for more information. Since most sequences of
characters are valid names, whitespace is more important than in other languages. In the example above the whitespace
around + is required, since 1+2 is a valid name.
Qualified names are used to refer to entities defined in other modules. For instance Prelude.Bool.true refers to
the name true defined in the module Prelude.Bool. See Module System for more information.

Literals

There are four types of literal values: integers, floats, characters, and strings. See Built-ins for the corresponding types,
and Literal Overloading for how to support literals for user-defined types.
Integers Integer values in decimal, hexadecimal (prefixed by 0x), or binary (prefixed by 0b) notation. The character
_ can be used to separate groups of digits. Non-negative numbers map by default to built-in natural numbers, but
can be overloaded. Negative numbers have no default interpretation and can only be used through overloading.
Examples: 123, 0xF0F080, -42, -0xF, 0b11001001, 1_000_000_000, 0b01001000_01001001.
Floats Floating point numbers in the standard notation (with square brackets denoting optional parts):

float ::= [-] decimal . decimal [exponent]


| [-] decimal exponent
exponent ::= (e | E) [+ | -] decimal

These map to built-in floats and cannot be overloaded.


Examples: 1.0, -5.0e+12, 1.01e-16, 4.2E9, 50e3.
Characters Character literals are enclosed in single quotes ('). They can be a single (unicode) character, other than
' or \, or an escaped character. Escaped characters start with a backslash \ followed by an escape code. Escape
codes are natural numbers in decimal or hexadecimal (prefixed by x) between 0 and 0x10ffff (1114111),
or one of the following special escape codes:

Code ASCII Code ASCII Code ASCII Code ASCII


a 7 b 8 t 9 n 10
v 11 f 12 \ \ ' '
" " NUL 0 SOH 1 STX 2
ETX 3 EOT 4 ENQ 5 ACK 6
BEL 7 BS 8 HT 9 LF 10
VT 11 FF 12 CR 13 SO 14
SI 15 DLE 16 DC1 17 DC2 18
DC3 19 DC4 20 NAK 21 SYN 22
ETB 23 CAN 24 EM 25 SUB 26
ESC 27 FS 28 GS 29 RS 30
US 31 SP 32 DEL 127

Character literals map to the built-in character type and cannot be overloaded.
Examples: 'A', '∀', '\x2200', '\ESC', '\32', '\n', '\'', '"'.
Strings String literals are sequences of, possibly escaped, characters enclosed in double quotes ". They follow the
same rules as character literals except that double quotes " need to be escaped rather than single quotes '.
String literals map to the built-in string type by default, but can be overloaded.

104 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Example: "PDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TODO


\"PDF TODOPDF TODOPDF TODO\"\n".

Holes

Holes are an integral part of the interactive development supported by the Emacs mode. Any text enclosed in {! and
!} is a hole and may contain nested holes. A hole with no contents can be written ?. There are a number of Emacs
commands that operate on the contents of a hole. The type checker ignores the contents of a hole and treats it as an
unknown (see Implicit Arguments).
Example: {! f {!x!} 5 !}

Comments

Single-line comments are written with a double dash -- followed by arbitrary text. Multi-line comments are enclosed
in {- and -} and can be nested. Comments cannot appear in string literals.
Example:

{- Here is a {- nested -}
comment -}
s : String --line comment {-
s = "{- not a comment -}"

Pragmas

Pragmas are special comments enclosed in {-# and #-} that have special meaning to the system. See Pragmas for a
full list of pragmas.

3.21.2 Layout

Agda is layout sensitive using similar rules as Haskell, with the exception that layout is mandatory: you cannot use
explicit {, } and ; to avoid it.
A layout block contains a sequence of statements and is started by one of the layout keywords:

abstract
constructor
do
field
instance
let
macro
mutual
postulate
primitive
private
variable
where

The first token after the layout keyword decides the indentation of the block. Any token indented more than this is
part of the previous statement, a token at the same level starts a new statement, and a token indented less lies outside
the block.

3.21. Lexical Structure 105


Agda User Manual, Release 2.6.2

data Nat : Set where -- starts a layout block


-- comments are not tokens
zero : Nat -- statement 1
suc : Nat → -- statement 2
Nat -- also statement 2

one : Nat -- outside the layout block


one = suc zero

Note that the indentation of the layout keyword does not matter.
If several layout blocks are started by layout keywords without line break in between (where line breaks inside block
comments do not count), then those blocks indented more than the last block go passive, meaning they cannot be
further extended by new statements:

private module M where postulate


A : Set -- module-block goes passive
B : Set -- postulate-block can still be extended
module N where -- private-block can still be extended

An Agda file contains one top-level layout block, with the special rule that the contents of the top-level module need
not be indented.

module Example where


NotIndented : Set1
NotIndented = Set

3.21.3 Literate Agda

Agda supports literate programming with multiple typesetting tools like LaTeX, Markdown and reStructuredText. For
instance, with LaTeX, everything in a file is a comment unless enclosed in \begin{code}, \end{code}. Literate
Agda files have special file extensions, like .lagda and .lagda.tex for LaTeX, .lagda.md for Markdown,
.lagda.rst for reStructuredText instead of .agda. The main use case for literate Agda is to generate LaTeX
documents from Agda code. See Generating HTML and Generating LaTeX for more information.

\documentclass{article}
% some preamble stuff
\begin{document}
Introduction usually goes here
\begin{code}
module MyPaper where
open import Prelude
five : Nat
five = 2 + 3
\end{code}
Now, conclusions!
\end{document}

106 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.22 Literal Overloading

3.22.1 Natural numbers

By default natural number literals are mapped to the built-in natural number type. This can be changed with the
FROMNAT built-in, which binds to a function accepting a natural number:
{-# BUILTIN FROMNAT fromNat #-}

This causes natural number literals n to be desugared to fromNat n, whenever fromNat is in scope unqualified
(renamed or not). Note that the desugaring happens before implicit argument are inserted so fromNat can have any
number of implicit or instance arguments. This can be exploited to support overloaded literals by defining a type class
containing fromNat:
module number-simple where

record Number {a} (A : Set a) : Set a where


field fromNat : Nat → A

open Number {{...}} public

{-# BUILTIN FROMNAT fromNat #-}

This definition requires that any natural number can be mapped into the given type, so it won’t work for types like
Fin n. This can be solved by refining the Number class with an additional constraint:
record Number {a} (A : Set a) : Set (lsuc a) where
field
Constraint : Nat → Set a
fromNat : (n : Nat) {{_ : Constraint n}} → A

open Number {{...}} public using (fromNat)

{-# BUILTIN FROMNAT fromNat #-}

This is the definition used in Agda.Builtin.FromNat. A Number instance for Nat is simply this:
instance
NumNat : Number Nat
NumNat .Number.Constraint _ = ⊤
NumNat .Number.fromNat m = m

A Number instance for Fin n can be defined as follows:


_≤_ : (m n : Nat) → Set
zero ≤ n = ⊤
suc m ≤ zero = ⊥
suc m ≤ suc n = m ≤ n

fromN≤ : ∀ m n → m ≤ n → Fin (suc n)


fromN≤ zero _ _ = zero
fromN≤ (suc _) zero ()
fromN≤ (suc m) (suc n) p = suc (fromN≤ m n p)

instance
NumFin : ∀ {n} → Number (Fin (suc n))
(continues on next page)

3.22. Literal Overloading 107


Agda User Manual, Release 2.6.2

(continued from previous page)


NumFin {n} .Number.Constraint m = m ≤ n
NumFin {n} .Number.fromNat m {{m≤n}} = fromN≤ m n m≤n

test : Fin 5
test = 3

It is important that the constraint for literals is trivial. Here, 3 ≤ 5 evaluates to ⊤ whose inhabitant is found by
unification.
Using predefined function from the standard library and instance NumNat, the NumFin instance can be simply:

open import Data.Fin using (Fin; #_)


open import Data.Nat using (suc; _≤?_)
open import Relation.Nullary.Decidable using (True)

instance
NumFin : ∀ {n} → Number (Fin n)
NumFin {n} .Number.Constraint m = True (suc m ≤? n)
NumFin {n} .Number.fromNat m {{m<n}} = #_ m {m<n = m<n}

3.22.2 Negative numbers

Negative integer literals have no default mapping and can only be used through the FROMNEG built-in. Binding this to
a function fromNeg causes negative integer literals -n to be desugared to fromNeg n, where n is a built-in natural
number. From Agda.Builtin.FromNeg:

record Negative {a} (A : Set a) : Set (lsuc a) where


field
Constraint : Nat → Set a
fromNeg : (n : Nat) {{_ : Constraint n}} → A

open Negative {{...}} public using (fromNeg)


{-# BUILTIN FROMNEG fromNeg #-}

3.22.3 Strings

String literals are overloaded with the FROMSTRING built-in, which works just like FROMNAT. If it is not bound
string literals map to built-in strings. From Agda.Builtin.FromString:

record IsString {a} (A : Set a) : Set (lsuc a) where


field
Constraint : String → Set a
fromString : (s : String) {{_ : Constraint s}} → A

open IsString {{...}} public using (fromString)


{-# BUILTIN FROMSTRING fromString #-}

3.22.4 Restrictions

Currently only integer and string literals can be overloaded.


Overloading does not work in patterns yet.

108 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.23 Mixfix Operators

A type name, function name, or constructor name can comprise one or more name parts if we separate them with
underscore characters _, and the resulting name can be used as an operator. From left to right, each argument goes in
the place of each underscore _.
For instance, we can join with underscores the name parts if, then, and else into a single name if_then_else_.
The application of the function name if_then_else_ to some arguments named x, y, and z can still be written as:
• a standard application by using the full name if_then_else_ x y z
• an operator application by placing the arguments between the name parts if x then y else z, leaving a
space between arguments and part names
• other sections of the full name, for instance leaving one or two underscores:
– (if_then y else z) x
– (if x then_else z) y
– if x then y else_ z
– if x then_else_ y z
– if_then y else_ x z
– (if_then_else z) x y
Examples of type names, function names, and constructor names as mixfix operators:

-- Example type name _⇒_


_⇒_ : Bool → Bool → Bool
true ⇒ b = b
false ⇒ _ = true

-- Example function name _and_


_and_ : Bool → Bool → Bool
true and x = x
false and _ = false

-- Example function name if_then_else_


if_then_else_ : {A : Set} → Bool → A → A → A
if true then x else y = x
if false then x else y = y

-- Example constructor name _::_


data List (A : Set) : Set where
nil : List A
_::_ : A → List A → List A

3.23.1 Precedence

Consider the expression true and false ⇒ false. Depending on which of _and_ and _⇒_ has more
precedence, it can either be read as (false and true) ⇒ false = true, or as false and (true ⇒
false) = true.
Each operator is associated to a precedence, which is a floating point number (can be negative and fractional!). The
default precedence for an operator is 20.

3.23. Mixfix Operators 109


Agda User Manual, Release 2.6.2

Note: Please note that -> is directly handled in the parser. As a result, the precedence of -> is lower than any
precedence you may declare with infixl and infixr.

If we give _and_ more precedence than _⇒_, then we will get the first result:

infix 30 _and_
-- infix 20 _⇒_ (default)

p-and : {x y z : Bool} → x and y ⇒ z ≡ (x and y) ⇒ z


p-and = refl

e-and : false and true ⇒ false ≡ true


e-and = refl

But, if we declare a new operator _and’_ and give it less precedence than _⇒_, then we will get the second result:

_and’_ : Bool → Bool → Bool


_and’_ = _and_
infix 15 _and’_
-- infix 20 _⇒_ (default)

p-⇒ : {x y z : Bool} → x and’ y ⇒ z ≡ x and’ (y ⇒ z)


p-⇒ = refl

e-⇒ : false and’ true ⇒ false ≡ false


e-⇒ = refl

Fixities can be changed when importing with a renaming directive:

open M using (_∙_)


open M renaming (_∙_ to infixl 10 _*_)

This code brings two instances of the operator _∙_ in scope:


• the first named _∙_ and with its original fixity
• the second named _*_ and with the fixity changed to act like a left associative operator of precedence 10.

3.23.2 Associativity

Consider the expression true ⇒ false ⇒ false. Depending on whether _⇒_ associates to the left or to
the right, it can be read as (false ⇒ true) ⇒ false = false, or false ⇒ (true ⇒ false) =
true, respectively.
If we declare an operator _⇒_ as infixr, it will associate to the right:

infixr 20 _⇒_

p-right : {x y z : Bool} → x ⇒ y ⇒ z ≡ x ⇒ (y ⇒ z)
p-right = refl

e-right : false ⇒ true ⇒ false ≡ true


e-right = refl

If we declare an operator _⇒’_ as infixl, it will associate to the left:

110 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

infixl 20 _⇒’_

_⇒’_ : Bool → Bool → Bool


_⇒’_ = _⇒_

p-left : {x y z : Bool} → x ⇒’ y ⇒’ z ≡ (x ⇒’ y) ⇒’ z
p-left = refl

e-left : false ⇒’ true ⇒’ false ≡ false


e-left = refl

3.23.3 Ambiguity and Scope

If you have not yet declared the fixity of an operator, Agda will complain if you try to use ambiguously:

e-ambiguous : Bool
e-ambiguous = true ⇒ true ⇒ true

Could not parse the application true ⇒ true ⇒ true


Operators used in the grammar:
⇒ (infix operator, level 20)

Fixity declarations may appear anywhere in a module that other declarations may appear. They then apply to the entire
scope in which they appear (i.e. before and after, but not outside).

3.23.4 Operators in telescopes

Agda does not yet support declaring the fixity of operators declared in telescopes, see Issue #1235
<https://github.com/agda/agda/issues/1235>.
However, the following hack currently works:

module _ {A : Set} (_+_ : A → A → A) (let infixl 5 _+_; _+_ = _+_) where

3.24 Module System

3.24.1 Module application

3.24.2 Anonymous modules

3.24.3 Basics

First let us introduce some terminology. A definition is a syntactic construction defining an entity such as a function or
a datatype. A name is a string used to identify definitions. The same definition can have many names and at different
points in the program it will have different names. It may also be the case that two definitions have the same name. In
this case there will be an error if the name is used.
The main purpose of the module system is to structure the way names are used in a program. This is done by
organising the program in an hierarchical structure of modules where each module contains a number of definitions
and submodules. For instance,

3.24. Module System 111


Agda User Manual, Release 2.6.2

module Main where

module B where
f : Nat → Nat
f n = suc n

g : Nat → Nat → Nat


g n m = m

Note that we use indentation to indicate which definitions are part of a module. In the example f is in the module
Main.B and g is in Main. How to refer to a particular definition is determined by where it is located in the module
hierarchy. Definitions from an enclosing module are referred to by their given names as seen in the type of f above.
To access a definition from outside its defining module a qualified name has to be used.

module Main2 where

module B where
f : Nat → Nat
f n = suc n

ff : Nat → Nat
ff x = B.f (B.f x)

To be able to use the short names for definitions in a module the module has to be opened.

module Main3 where

module B where
f : Nat → Nat
f n = suc n

open B

ff : Nat → Nat
ff x = f (f x)

If A.qname refers to a definition d, then after open A, qname will also refer to d. Note that qname can itself be a
qualified name. Opening a module only introduces new names for a definition, it never removes the old names. The
policy is to allow the introduction of ambiguous names, but give an error if an ambiguous name is used.
Modules can also be opened within a local scope by putting the open B within a where clause:

ff1 : Nat → Nat


ff1 x = f (f x) where open B

3.24.4 Private definitions

To make a definition inaccessible outside its defining module it can be declared private. A private definition is
treated as a normal definition inside the module that defines it, but outside the module the definition has no name.
In a dependently type setting there are some problems with private definitions—since the type checker performs
computations, private names might show up in goals and error messages. Consider the following (contrived) example

module Main4 where


module A where

(continues on next page)

112 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


private
IsZero’ : Nat → Set
IsZero’ zero = ⊤
IsZero’ (suc n) = ⊥

IsZero : Nat → Set


IsZero n = IsZero’ n

open A
prf : (n : Nat) → IsZero n
prf n = ?

The type of the goal ?0 is IsZero n which normalises to IsZero’ n. The question is how to display this normal
form to the user. At the point of ?0 there is no name for IsZero’. One option could be try to fold the term and print
IsZero n. This is a very hard problem in general, so rather than trying to do this we make it clear to the user that
IsZero’ is something that is not in scope and print the goal as ;Main4 .A.IsZero’ n. The leading semicolon
indicates that the entity is not in scope. The same technique is used for definitions that only have ambiguous names.
In effect using private definitions means that, from the user’s perspective, we do not have subject reduction. This is
just an illusion, however—the type checker has full access to all definitions.

3.24.5 Name modifiers

An alternative to making definitions private is to exert finer control over what names are introduced when opening
a module. This is done by qualifying an open statement with one or more of the modifiers using, hiding, or
renaming. You can combine both using and hiding with renaming, but not with each other. The effect of

open A using (xs) renaming (ys to zs)

is to introduce the names xs and zs where xs refers to the same definition as A.xs and zs refers to A.ys. We
do not permit xs, ys and zs to overlap. The other forms of opening are defined in terms of this one. An omitted
renaming modifier is equivalent to an empty renaming.
To refer to a module M inside A you write module M. For instance,

open A using (module M)

Since 2.6.1: The fixity of an operator can be set or changed in a renaming directive:

module ExampleRenamingFixity where

module ArithFoo where


postulate
A : Set
_&_ _^_ : A → A → A
infixr 10 _&_

open ArithFoo renaming (_&_ to infixl 8 _+_; _^_ to infixl 10 _^_)

Here, we change the fixity of _&_ while renaming it to _+_, and assign a new fixity to _^_ which has the default
fixity in module ArithFoo.

3.24. Module System 113


Agda User Manual, Release 2.6.2

3.24.6 Re-exporting names

A useful feature is the ability to re-export names from another module. For instance, one may want to create a module
to collect the definitions from several other modules. This is achieved by qualifying the open statement with the public
keyword:

module Example where

module Nat1 where

data Nat1 : Set where


zero : Nat1
suc : Nat1 → Nat1

module Bool1 where

data Bool1 : Set where


true false : Bool1

module Prelude where

open Nat1 public


open Bool1 public

isZero : Nat1 → Bool1


isZero zero = true
isZero (suc _) = false

The module Prelude above exports the names Nat, zero, Bool, etc., in addition to isZero.

3.24.7 Parameterised modules

So far, the module system features discussed have dealt solely with scope manipulation. We now turn our attention to
some more advanced features.
It is sometimes useful to be able to work temporarily in a given signature. For instance, when defining functions for
sorting lists it is convenient to assume a set of list elements A and an ordering over A. In Coq this can be done in two
ways: using a functor, which is essentially a function between modules, or using a section. A section allows you to
abstract some arguments from several definitions at once. We introduce parameterised modules analogous to sections
in Coq. When declaring a module you can give a telescope of module parameters which are abstracted from all the
definitions in the module. For instance, a simple implementation of a sorting function looks like this:

module Sort (A : Set)(_≤_ : A → A → Bool) where


insert : A → List A → List A
insert x [] = x :: []
insert x (y :: ys) with x ≤ y
insert x (y :: ys) | true = x :: y :: ys
insert x (y :: ys) | false = y :: insert x ys

sort : List A → List A


sort [] = []
sort (x :: xs) = insert x (sort xs)

As mentioned parametrising a module has the effect of abstracting the parameters over the definitions in the module,
so outside the Sort module we have

114 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Sort.insert : (A : Set)(_≤_ : A → A → Bool) →


A → List A → List A
Sort.sort : (A : Set)(_≤_ : A → A → Bool) →
List A → List A

For function definitions, explicit module parameter become explicit arguments to the abstracted function, and implicit
parameters become implicit arguments. For constructors, however, the parameters are always implicit arguments. This
is a consequence of the fact that module parameters are turned into datatype parameters, and the datatype parameters
are implicit arguments to the constructors. It also happens to be the reasonable thing to do.
Something which you cannot do in Coq is to apply a section to its arguments. We allow this through the module
application statement. In our example:

module SortNat = Sort Nat leqNat

This will define a new module SortNat as follows

module SortNat where


insert : Nat → List Nat → List Nat
insert = Sort.insert Nat leqNat

sort : List Nat → List Nat


sort = Sort.sort Nat leqNat

The new module can also be parameterised, and you can use name modifiers to control what definitions from the
original module are applied and what names they have in the new module. The general form of a module application
is

module M1 Δ = M2 terms modifiers

A common pattern is to apply a module to its arguments and then open the resulting module. To simplify this we
introduce the short-hand

open module M1 Δ = M2 terms [public] mods

for

module M1 Δ = M2 terms mods


open M1 [public]

3.24.8 Splitting a program over multiple files

When building large programs it is crucial to be able to split the program over multiple files and to not have to type
check and compile all the files for every change. The module system offers a structured way to do this. We define
a program to be a collection of modules, each module being defined in a separate file. To gain access to a module
defined in a different file you can import the module:

import M

In order to implement this we must be able to find the file in which a module is defined. To do this we require that the
top-level module A.B.C is defined in the file C.agda in the directory A/B/. One could imagine instead to give a file
name to the import statement, but this would mean cluttering the program with details about the file system which is
not very nice.

3.24. Module System 115


Agda User Manual, Release 2.6.2

When importing a module M, the module and its contents are brought into scope as if the module had been defined in
the current file. In order to get access to the unqualified names of the module contents it has to be opened. Similarly
to module application we introduce the short-hand

open import M

for

import M
open M

Sometimes the name of an imported module clashes with a local module. In this case it is possible to import the
module under a different name.

import M as M’

It is also possible to attach modifiers to import statements, limiting or changing what names are visible from inside the
module. Note that modifiers attached to open import statements apply to the open statement and not the import
statement.

3.24.9 Datatype modules and record modules

When you define a datatype it also defines a module so constructors can now be referred to qualified by their data type.
For instance, given:

module DatatypeModules where

data Nat2 : Set where


zero : Nat2
suc : Nat2 → Nat2

data Fin : Nat2 → Set where


zero : ∀ {n} → Fin (suc n)
suc : ∀ {n} → Fin n → Fin (suc n)

you can refer to the constructors unambiguously as Nat2 .zero, Nat2 .suc, Fin.zero, and Fin.suc (Nat2 and
Fin are modules containing the respective constructors). Example:

inj : (n m : Nat2 ) → Nat2 .suc n ≡ suc m → n ≡ m


inj .m m refl = refl

Previously you had to write something like

inj1 : (n m : Nat2 ) → _≡_ {A = Nat2 } (suc n) (suc m) → n ≡ m


inj1 .m m refl = refl

to make the type checker able to figure out that you wanted the natural number suc in this case.
Also record declarations define a corresponding module, see Record modules.

3.25 Mutual Recursion

Agda offers multiple ways to write mutually-defined data types, record types and functions.
• Old-style mutual blocks

116 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• Forward declaration
• Interleaved mutual blocks
The last two are more expressive than the first one as they allow the interleaving of declarations and definitions thus
making it possible for some types to refere to the constructors of a mutually-defined datatype.

3.25.1 Interleaved mutual blocks

Mutual recursive functions can be written by placing them inside an interleaved mutual block. The type
signature of each function must come before its defining clauses and its usage sites on the right-hand side of other
functions. The clauses for different functions can be interleaved e.g. for pedagogical purposes:

interleaved mutual

-- Declarations:
even : Nat → Bool
odd : Nat → Bool

-- zero is even, not odd


even zero = true
odd zero = false

-- suc case: switch evenness on the predecessor


even (suc n) = odd n
odd (suc n) = even n

You can mix arbitrary declarations, such as modules and postulates, with mutually recursive definitions. For data types
and records the following syntax is used to separate the declaration from the introduction of constructors in one or
many data ... where blocks:

interleaved mutual

-- Declaration of a product record, a universe of codes, and a decoding function


record _×_ (A B : Set) : Set
data U : Set
El : U → Set

-- We have a code for the type of natural numbers in our universe


data U where `Nat : U
El `Nat = Nat

-- Btw we know how to pair values in a record


record _×_ A B where
inductive; constructor _,_
field fst : A; snd : B

-- And we have a code for pairs in our universe


data _ where
_`×_ : (A B : U) → U
El (A `× B) = El A × El B

-- we can now build types of nested pairs of natural numbers


ty-example : U
ty-example = `Nat `× ((`Nat `× `Nat) `× `Nat)

-- and their values


(continues on next page)

3.25. Mutual Recursion 117


Agda User Manual, Release 2.6.2

(continued from previous page)


val-example : El ty-example
val-example = 0 , ((1 , 2) , 3)

You can mix constructors for different data types in a data _ where block (underscore instead of name).
The interleaved mutual blocks get desugared into the Forward declaration blocks described below by:
• leaving the signatures where they are,
• grouping the clauses for a function together with the first of them, and
• grouping the constructors for a datatype together with the first of them.

3.25.2 Forward declaration

Mutual recursive functions can be written by placing the type signatures of all mutually recursive function before their
definitions. The span of the mutual block will be automatically inferred by Agda:

f : A
g : B[f]
f = a[f, g]
g = b[f, g].

You can mix arbitrary declarations, such as modules and postulates, with mutually recursive definitions. For data types
and records the following syntax is used to separate the declaration from the definition:

-- Declaration.
data Vec (A : Set) : Nat → Set -- Note the absence of ‘where’.

-- Definition.
data Vec A where -- Note the absence of a type signature.
[] : Vec A zero
_::_ : {n : Nat} → A → Vec A n → Vec A (suc n)

-- Declaration.
record Sigma (A : Set) (B : A → Set) : Set

-- Definition.
record Sigma A B where
constructor _,_
field fst : A
snd : B fst

The parameter lists in the second part of a data or record declaration behave like variables left-hand sides (although
infix syntax is not supported). That is, they should have no type signatures, but implicit parameters can be omitted or
bound by name.
Such a separation of declaration and definition is for instance needed when defining a set of codes for types and their
interpretation as actual types (a so-called universe):

-- Declarations.
data TypeCode : Set
Interpretation : TypeCode → Set

-- Definitions.
data TypeCode where
(continues on next page)

118 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


nat : TypeCode
pi : (a : TypeCode) (b : Interpretation a → TypeCode) → TypeCode

Interpretation nat = Nat


Interpretation (pi a b) = (x : Interpretation a) → Interpretation (b x)

Note: In contrast to Interleaved mutual blocks, in forward-declaration style we can only have one data ...
where block per data type.

When making separated declarations/definitions private or abstract you should attach the private keyword to the
declaration and the abstract keyword to the definition. For instance, a private, abstract function can be defined as

private
f : A
abstract
f = e

3.25.3 Old-style mutual blocks

Mutual recursive functions can be written by placing the type signatures of all mutually recursive function before their
definitions:

mutual
f : A
f = a[f, g]

g : B[f]
g = b[f, g]

Using the mutual keyword, the universe example from above is expressed as follows:

mutual
data TypeCode : Set where
nat : TypeCode
pi : (a : TypeCode) (b : Interpretation a → TypeCode) → TypeCode

Interpretation : TypeCode → Set


Interpretation nat = Nat
Interpretation (pi a b) = (x : Interpretation a) → Interpretation (b x)

This alternative syntax desugars into the new syntax by sorting the content of the mutual block into a declaration and
a definition part and placing the declarations before the definitions.
Declarations comprise:
• Type signatures of functions, data and record declarations, unquoteDecl. (Function includes here
postulate and primitive etc.)
• Module statements, such as module aliases, import and open statements.
• Pragmas that only need the name, but not the definition of the thing they affect (e.g. INJECTIVE).
Definitions comprise:
• Function clauses, data constructors and record definitions, unquoteDef.

3.25. Mutual Recursion 119


Agda User Manual, Release 2.6.2

• pattern synonym definitions.


• Pragmas that need the definition, e.g. INLINE, ETA, etc.
• Pragmas that are not needed for type checking, like compiler pragmas.
Module definitions with module ... where are not supported in old-style mutual blocks.

3.26 Pattern Synonyms

A pattern synonym is a declaration that can be used on the left hand side (when pattern matching) as well as the right
hand side (in expressions). For example:

data Nat : Set where


zero : Nat
suc : Nat → Nat

pattern z = zero
pattern ss x = suc (suc x)

f : Nat → Nat
f z = z
f (suc z) = ss z
f (ss n) = n

Pattern synonyms are implemented by substitution on the abstract syntax, so definitions are scope-checked but not
type-checked. They are particularly useful for universe constructions.

3.26.1 Overloading

Pattern synonyms can be overloaded as long as all candidates have the same shape. Two pattern synonym definitions
have the same shape if they are equal up to variable and constructor names. Shapes are checked at resolution time and
after expansion of nested pattern synonyms.
For example:

data List (A : Set) : Set where


lnil : List A
lcons : A → List A → List A

data Vec (A : Set) : Nat → Set where


vnil : Vec A zero
vcons : ∀ {n} → A → Vec A n → Vec A (suc n)

pattern [] = lnil
pattern [] = vnil

pattern _::_ x xs = lcons x xs


pattern _::_ y ys = vcons y ys

lmap : ∀ {A B} → (A → B) → List A → List B


lmap f [] = []
lmap f (x :: xs) = f x :: lmap f xs

vmap : ∀ {A B n} → (A → B) → Vec A n → Vec B n


(continues on next page)

120 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


vmap f [] = []
vmap f (x :: xs) = f x :: vmap f xs

Flipping the arguments in the synonym for vcons, changing it to pattern _::_ ys y = vcons y ys, results
in the following error when trying to use the synonym:

Cannot resolve overloaded pattern synonym _::_, since candidates


have different shapes:
pattern _::_ x xs = lcons x xs
at pattern-synonyms.lagda.rst:51,13-16
pattern _::_ ys y = vcons y ys
at pattern-synonyms.lagda.rst:52,13-16
(hint: overloaded pattern synonyms must be equal up to variable and
constructor names)
when checking that the clause lmap f (x :: xs) = f x :: lmap f xs has
type {A B : Set} → (A → B) → List A → List B

3.26.2 Refolding

For each pattern pattern lhs = rhs, Agda declares a DISPLAY pragma refolding rhs to lhs (see The DIS-
PLAY pragma for more details).

3.27 Positivity Checking

Note: This is a stub.

3.27.1 The NO_POSITIVITY_CHECK pragma

The pragma switches off the positivity checker for data/record definitions and mutual blocks. This pragma was added
in Agda 2.5.1
The pragma must precede a data/record definition or a mutual block. The pragma cannot be used in --safe mode.
Examples:
• Skipping a single data definition:

{-# NO_POSITIVITY_CHECK #-}


data D : Set where
lam : (D → D) → D

• Skipping a single record definition:

{-# NO_POSITIVITY_CHECK #-}


record U : Set where
field ap : U → U

• Skipping an old-style mutual block. Somewhere within a mutual block before a data/record definition:

3.27. Positivity Checking 121


Agda User Manual, Release 2.6.2

mutual
data D : Set where
lam : (D → D) → D

{-# NO_POSITIVITY_CHECK #-}


record U : Set where
field ap : U → U

• Skipping an old-style mutual block. Before the mutual keyword:

{-# NO_POSITIVITY_CHECK #-}


mutual
data D : Set where
lam : (D → D) → D

record U : Set where


field ap : U → U

• Skipping a new-style mutual block. Anywhere before the declaration or the definition of a data/record in the
block:

record U : Set
data D : Set

record U where
field ap : U → U

{-# NO_POSITIVITY_CHECK #-}


data D where
lam : (D → D) → D

3.27.2 POLARITY pragmas

Polarity pragmas can be attached to postulates. The polarities express how the postulate’s arguments are used. The
following polarities are available:
• _: Unused.
• ++: Strictly positive.
• +: Positive.
• -: Negative.
• *: Unknown/mixed.
Polarity pragmas have the form {-# POLARITY name <zero or more polarities> #-}, and can be
given wherever fixity declarations can be given. The listed polarities apply to the given postulate’s arguments (ex-
plicit/implicit/instance), from left to right. Polarities currently cannot be given for module parameters. If the postulate
takes n arguments (excluding module parameters), then the number of polarities given must be between 0 and n (in-
clusive).
Polarity pragmas make it possible to use postulated type formers in recursive types in the following way:

postulate
‖_‖ : Set → Set

(continues on next page)

122 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


{-# POLARITY ‖_‖ ++ #-}

data D : Set where


c : ‖ D ‖ → D

Note that one can use postulates that may seem benign, together with polarity pragmas, to prove that the empty type
is inhabited:

postulate
_⇒_ : Set → Set → Set
lambda : {A B : Set} → (A → B) → A ⇒ B
apply : {A B : Set} → A ⇒ B → A → B

{-# POLARITY _⇒_ ++ #-}

data ⊥ : Set where

data D : Set where


c : D ⇒ ⊥ → D

not-inhabited : D → ⊥
not-inhabited (c f) = apply f (c f)

d : D
d = c (lambda not-inhabited)

bad : ⊥
bad = not-inhabited d

Polarity pragmas are not allowed in safe mode.

3.28 Postulates

A postulate is a declaration of an element of some type without an accompanying definition. With postulates we can
introduce elements in a type without actually giving the definition of the element itself.
The general form of a postulate declaration is as follows:

postulate
c11 ... c1i : <Type>
...
cn1 ... cnj : <Type>

Example:

postulate
A B : Set
a : A
b : B
_=AB=_ : A -> B -> Set
a==b : a =AB= b

Introducing postulates is in general not recommended. Once postulates are introduced the consistency of the whole
development is at risk, because there is nothing that prevents us from introducing an element in the empty set.

3.28. Postulates 123


Agda User Manual, Release 2.6.2

data False : Set where

postulate bottom : False

A preferable way to work is to define a module parametrised by the elements we need

module Absurd (bt : False) where

-- ...

module M (A B : Set) (a : A) (b : B)
(_=AB=_ : A -> B -> Set) (a==b : a =AB= b) where

-- ...

3.28.1 Postulated built-ins

Some Built-ins such as Float and Char are introduced as a postulate and then given a meaning by the corresponding
{-# BUILTIN ... #-} pragma.

3.29 Pragmas

Pragmas are comments that are not ignored by Agda but have some special meaning. The general format is:

{-# <PRAGMA_NAME> <arguments> #-}

3.29.1 Index of pragmas

• BUILTIN
• CATCHALL
• COMPILE
• DISPLAY
• FOREIGN
• INJECTIVE
• INLINE
• NO_POSITIVITY_CHECK
• NO_TERMINATION_CHECK
• NO_UNIVERSE_CHECK
• NOINLINE
• NON_COVERING
• NON_TERMINATING
• OPTIONS
• POLARITY

124 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• REWRITE
• STATIC
• TERMINATING
• WARNING_ON_USAGE
• WARNING_ON_IMPORT
See also Command-line and pragma options.

The DISPLAY pragma

Users can declare a DISPLAY pragma:

{-# DISPLAY f e1 .. en = e #-}

This causes f e1 .. en to be printed in the same way as e, where ei can bind variables used in e. The expressions
ei and e are scope checked, but not type checked.
For example this can be used to print overloaded (instance) functions with the overloaded name:

instance
NumNat : Num Nat
NumNat = record { ..; _+_ = natPlus }

{-# DISPLAY natPlus a b = a + b #-}

Limitations
• Left-hand sides are restricted to variables, constructors, defined functions or types, and literals. In particular,
lambdas are not allowed in left-hand sides.
• Since DISPLAY pragmas are not type checked implicit argument insertion may not work properly if the type of
f computes to an implicit function space after pattern matching.

The INJECTIVE pragma

Injective pragmas can be used to mark a definition as injective for the pattern matching unifier. This can be used as a
version of --injective-type-constructors that only applies to specific datatypes.
Example:

open import Agda.Builtin.Equality


open import Agda.Builtin.Nat

data Fin : Nat → Set where


zero : {n : Nat} → Fin (suc n)
suc : {n : Nat} → Fin n → Fin (suc n)

{-# INJECTIVE Fin #-}

Fin-injective : {m n : Nat} → Fin m ≡ Fin n → m ≡ n


Fin-injective refl = refl

Aside from datatypes, this pragma can also be used to mark other definitions as being injective (for example postu-
lates).

3.29. Pragmas 125


Agda User Manual, Release 2.6.2

The INLINE and NOINLINE pragmas

A definition marked with an INLINE pragma is inlined during compilation. If it is a simple definition that does no
pattern matching, it is also inlined in function bodies at type-checking time.
When the --auto-inline command-line option is enabled, definitions are automatically marked INLINE if they
satisfy the following criteria:
• No pattern matching.
• Uses each argument at most once.
• Does not use all its arguments.
Automatic inlining can be prevented using the NOINLINE pragma.
Example:

-- Would be auto-inlined since it doesn't use the type arguments.


_∘_ : {A B C : Set} → (B → C) → (A → B) → A → C
(f ∘ g) x = f (g x)

{-# NOINLINE _∘_ #-} -- prevents auto-inlining

-- Would not be auto-inlined since it's using all its arguments


_o_ : (Set → Set) → (Set → Set) → Set → Set
(F o G) X = F (G X)

{-# INLINE _o_ #-} -- force inlining

The NON_COVERING pragma

New in version 2.6.1.


The NON_COVERING pragma can be placed before a function (or a block of mutually defined functions) which the
user knows to be partial. To be used as a version of --allow-incomplete-matches that only applies to specific
functions.

The OPTIONS pragma

Some options can be given at the top of .agda files in the form
{-# OPTIONS --{opt1 } --{opt2 } ... #-}
The possible options are listed in Command-line and pragma options.

The WARNING_ON_ pragmas

A library author can use a WARNING_ON_USAGE pragma to attach to a defined name a warning to be raised whenever
this name is used (since Agda 2.5.4).
Similarly they can use a WARNING_ON_IMPORT pragma to attach to a module a warning to be raised whenever this
module is imported (since Agda 2.6.1).
This would typically be used to declare a name or a module ‘DEPRECATED’ and advise the end-user to port their
code before the feature is dropped.

126 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Users can turn these warnings off by using the --warn=noUserWarning option. For more information about the
warning machinery, see Warnings.
Example:

-- The new name for the identity


id : {A : Set} → A → A
id x = x

-- The deprecated name


𝜆x→x = id

-- The warning
{-# WARNING_ON_USAGE 𝜆x→x "DEPRECATED: Use `id` instead of `𝜆x→x`" #-}
{-# WARNING_ON_IMPORT "DEPRECATED: Use module `Function.Identity` rather than
˓→`Identity`" #-}

3.30 Prop

Prop is Agda’s built-in sort of definitionally proof-irrelevant propositions. It is similar to the sort Set, but all elements
of a type in Prop are considered to be (definitionally) equal.
The implementation of Prop is based on the POPL 2019 paper Definitional Proof-Irrelevance without K by Gaëtan
Gilbert, Jesper Cockx, Matthieu Sozeau, and Nicolas Tabareau.

3.30.1 Usage

Just as for Set, we can define new types in Prop’s as data or record types:

data ⊥ : Prop where

record ⊤ : Prop where


constructor tt

When defining a function from a data type in Prop to a type in Set, pattern matching is restricted to the absurd
pattern ():

absurd : (A : Set) → ⊥ → A
absurd A ()

Unlike for Set, all elements of a type in Prop are definitionally equal. This implies all applications of absurd are
the same:

only-one-absurdity : {A : Set} → (p q : ⊥) → absurd A p ≡ absurd A q


only-one-absurdity p q = refl

Since pattern matching on datatypes in Prop is limited, it is recommended to define types in Prop as recursive
functions rather than inductive datatypes. For example, the relation _≤_ on natural numbers can be defined as follows:

_≤_ : Nat → Nat → Prop


zero ≤ y = ⊤
suc x ≤ zero = ⊥
suc x ≤ suc y = x ≤ y

The induction principle for _≤_ can then be defined by matching on the arguments of type Nat:

3.30. Prop 127


Agda User Manual, Release 2.6.2

module _ (P : (m n : Nat) → Set)


(pzy : (y : Nat) → P zero y)
(pss : (x y : Nat) → P x y → P (suc x) (suc y)) where

≤-ind : (m n : Nat) → m ≤ n → P m n
≤-ind zero y pf = pzy y
≤-ind (suc x) (suc y) pf = pss x y (≤-ind x y pf)
≤-ind (suc _) zero ()

Note that while it is also possible to define _≤_ as a datatype in Prop, it is hard to use that version because of the
limitations to matching.
When defining a record type in Set, the types of the fields can be both in Set and Prop. For example:

record Fin (n : Nat) : Set where


constructor _[_]
field
J_K : Nat
proof : suc J_K ≤ n
open Fin

Fin-≡ : ∀ {n} (x y : Fin n) → J x K ≡ J y K → x ≡ y


Fin-≡ x y refl = refl

3.30.2 The predicative hierarchy of Prop

Just as for Set, Agda has a predicative hierarchy of sorts Prop0 (= Prop), Prop1 , Prop2 , . . . where Prop0
: Set1 , Prop1 : Set2 , Prop2 : Set3 , etc. Like Set, Prop also supports universe polymorphism (see
universe levels), so for each l : Level we have the sort Prop l . For example:

True : ∀ {l } → Prop (lsuc l )


True {l } = ∀ (P : Prop l ) → P → P

3.30.3 The propositional squash type

When defining a datatype in Prop l , it is allowed to have constructors that take arguments in Set l ´ for any l ´ ≤
l . For example, this allows us to define the propositional squash type and its eliminator:

data Squash {l } (A : Set l ) : Prop l where


squash : A → Squash A

squash-elim : ∀ {l 1 l 2 } (A : Set l 1 ) (P : Prop l 2 ) → (A → P) → Squash A → P


squash-elim A P f (squash x) = f x

This type allows us to simulate Agda’s existing irrelevant arguments (see irrelevance) by replacing .A with Squash A.

3.30.4 Limitations

It is possible to define an equality type in Prop as follows:


.
data _=_ {l } {A : Set l } (x : A) : A → Prop l where
.
refl : x = x

128 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

However, the corresponding eliminator cannot be defined because of the limitations on pattern matching. As a conse-
quence, this equality type is only useful for refuting impossible equations:
.
0̸≡1 : 0 = 1 → ⊥
0̸≡1 ()

3.31 Record Types

• Example: the Pair type constructor


• Declaring, constructing and decomposing records
– Declaring record types
– Constructing record values
– Decomposing record values
– Record update
• Record modules
• Eta-expansion
• Recursive records
• Instance fields

Records are types for grouping values together. They generalise the dependent product type by providing named fields
and (optional) further components.

3.31.1 Example: the Pair type constructor

Record types can be declared using the record keyword

record Pair (A B : Set) : Set where


field
fst : A
snd : B

This defines a new type constructor Pair : Set → Set → Set and two projection functions

Pair.fst : {A B : Set} → Pair A B → A


Pair.snd : {A B : Set} → Pair A B → B

Elements of record types can be defined using a record expression

p23 : Pair Nat Nat


p23 = record { fst = 2; snd = 3 }

or using copatterns. Copatterns may be used prefix

p34 : Pair Nat Nat


Pair.fst p34 = 3
Pair.snd p34 = 4

3.31. Record Types 129


Agda User Manual, Release 2.6.2

suffix (in which case they are written prefixed with a dot)

p56 : Pair Nat Nat


p56 .Pair.fst = 5
p56 .Pair.snd = 6

or using an anonymous copattern-matching lambda (you may only use the suffix form of copatterns in this case)

p78 : Pair Nat Nat


p78 = 𝜆 where
.Pair.fst → 7
.Pair.snd → 8

If you use the constructor keyword, you can also use the named constructor to define elements of the record type:

record Pair (A B : Set) : Set where


constructor _,_
field
fst : A
snd : B

p45 : Pair Nat Nat


p45 = 4 , 5

In this sense, record types behave much like single constructor datatypes (but see Eta-expansion below).

3.31.2 Declaring, constructing and decomposing records

Declaring record types

The general form of a record declaration is as follows:

record <recordname> <parameters> : Set <level> where


<directives>
constructor <constructorname>
field
<fieldname1> : <type1>
<fieldname2> : <type2>
-- ...
<declarations>

All the components are optional, and can be given in any order. In particular, fields can be given in more than one
block, interspersed with other declarations. Each field is a component of the record. Types of later fields can depend
on earlier fields.
The directives available are eta-equality, no-eta-equality, pattern (see Eta-expansion), inductive
and co-inductive (see Recursive records).

Constructing record values

Record values are constructed by giving a value for each record field:

record { <fieldname1> = <term1> ; <fieldname2> = <term2> ; ... }

where the types of the terms match the types of the fields. If a constructor <constructorname> has been declared
for the record, this can also be written

130 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

<constructorname> <term1> <term2> ...

For named definitions, this can also be expressed using copatterns:

<named-def> : <recordname> <parameters>


<recordname>.<fieldname1> <named-def> = <term1>
<recordname>.<fieldname2> <named-def> = <term2>
...

Records can also be constructed by updating other records.

Building records from modules

The record { <fields> } syntax also accepts module names. Fields are defined using the corresponding defi-
nitions from the given module. For instance assuming this record type R and module M:

record R : Set where


field
x : X
y : Y
z : Z

module M where
x = ...
y = ...

r : R
r = record { M; z = ... }

This construction supports any combination of explicit field definitions and applied modules. If a field is both given
explicitly and available in one of the modules, then the explicit one takes precedence. If a field is available in more
than one module then this is ambiguous and therefore rejected. As a consequence the order of assignments does not
matter.
The modules can be both applied to arguments and have import directives such as hiding, using, and renaming. Here
is a contrived example building on the example above:

module M2 (a : A) where
w = ...
z = ...

r2 : A → R
r2 a = record { M hiding (y); M2 a renaming (w to y) }

Decomposing record values

With the field name, we can project the corresponding component out of a record value. It is also possible to pattern
match against inductive records:

sum : Pair Nat Nat → Nat


sum (x , y) = x + y

Or, using a let binding record pattern:

3.31. Record Types 131


Agda User Manual, Release 2.6.2

sum' : Pair Nat Nat → Nat


sum' p = let (x , y) = p in x + y

Note: Naming the constructor is not required to enable pattern matching against record values. Record expressions
can appear as patterns.

Record update

Assume that we have a record type and a corresponding value:

record MyRecord : Set where


field
a b c : Nat

old : MyRecord
old = record { a = 1; b = 2; c = 3 }

Then we can update (some of) the record value’s fields in the following way:

new : MyRecord
new = record old { a = 0; c = 5 }

Here new normalises to record { a = 0; b = 2; c = 5 }. Any expression yielding a value of type


MyRecord can be used instead of old. Using that records can be built from module names, together with the
fact that all records define a module, this can also be written as

new' : MyRecord
new' = record { MyRecord old; a = 0; c = 5}

Record updating is not allowed to change types: the resulting value must have the same type as the original one,
including the record parameters. Thus, the type of a record update can be inferred if the type of the original record can
be inferred.
The record update syntax is expanded before type checking. When the expression

record old { upd-fields }

is checked against a record type R, it is expanded to

let r = old in record { new-fields }

where old is required to have type R and new-fields is defined as follows: for each field x in R,
• if x = e is contained in upd-fields then x = e is included in new-fields, and otherwise
• if x is an explicit field then x = R.x r is included in new-fields, and
• if x is an implicit or instance field, then it is omitted from new-fields.
The reason for treating implicit and instance fields specially is to allow code like the following:

data Vec (A : Set) : Nat → Set where


[] : Vec A zero
_::_ : ∀{n} → A → Vec A n → Vec A (suc n)

(continues on next page)

132 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


record R : Set where
field
{length} : Nat
vec : Vec Nat length
-- More fields ...

xs : R
xs = record { vec = 0 :: 1 :: 2 :: [] }

ys = record xs { vec = 0 :: [] }

Without the special treatment the last expression would need to include a new binding for length (for instance
length = _).

3.31.3 Record modules

Along with a new type, a record declaration also defines a module with the same name, parameterised over an element
of the record type containing the projection functions. This allows records to be “opened”, bringing the fields into
scope. For instance

swap : {A B : Set} → Pair A B → Pair B A


swap p = snd , fst
where open Pair p

In the example, the record module Pair has the shape

module Pair {A B : Set} (p : Pair A B) where


fst : A
snd : B

It’s possible to add arbitrary definitions to the record module, by defining them inside the record declaration

record Functor (F : Set → Set) : Set1 where


field
fmap : ∀ {A B} → (A → B) → F A → F B

_<$_ : ∀ {A B} → A → F B → F A
x <$ fb = fmap (𝜆 _ → x) fb

Note: In general new definitions need to appear after the field declarations, but simple non-recursive function def-
initions without pattern matching can be interleaved with the fields. The reason for this restriction is that the type
of the record constructor needs to be expressible using let-expressions. In the example below D1 can only contain
declarations for which the generated type of mkR is well-formed.

record R Γ : Set𝑖 where


constructor mkR
field f1 : A1
D1
field f2 : A2

mkR : ∀ {Γ} (f1 : A1 ) (let D1 ) (f2 : A2 ) → R Γ

3.31. Record Types 133


Agda User Manual, Release 2.6.2

3.31.4 Eta-expansion

The eta (𝜂) rule for a record type


record R : Set where
field
a : A
b : B
c : C

states that every x : R is definitionally equal to record { a = R.a x ; b = R.b x ; c = R.c x }.


By default, all (inductive) record types enjoy 𝜂-equality if the positivity checker has confirmed it is safe to have it. The
keywords eta-equality/no-eta-equality enable/disable 𝜂 rules for the record type being declared.

3.31.5 Recursive records

Recursive records need to be declared as either inductive or coinductive.


record Tree (A : Set) : Set where
inductive
constructor tree
field
elem : A
subtrees : List (Tree A)

record Stream (A : Set) : Set where


coinductive
constructor _::_
field
head : A
tail : Stream A

Inductive records have eta-equality on by default, while no-eta-equality is the default for coinductive
records. In fact, the eta-equality and coinductive directives are not allowed together, since this can easily
make Agda loop. This can be overridden at your own risk by using the pragma ETA instead.
It is possible to pattern match on inductive records, but not on coinductive ones.
However, inductive records without 𝜂-equality do not support both matching on the record constructor and construction
of record elements by copattern matching. It has been discovered that the combination of both leads to loss of subject
reduction, i.e., reduction does not preserve typing. For records without 𝜂, matching on the record constructor is off
by default and construction by copattern matching is on. If you want the converse, you can add the record directive
pattern:
record HereditaryList : Set where
inductive
no-eta-equality
pattern
field sublists : List HereditaryList

pred : HereditaryList → List HereditaryList


pred record{ sublists = ts } = ts

3.31.6 Instance fields

Instance fields, that is record fields marked with {{ }} can be used to model “superclass” dependencies. For example:

134 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

record Eq (A : Set) : Set where


field
_==_ : A → A → Bool

open Eq {{...}}

record Ord (A : Set) : Set where


field
_<_ : A → A → Bool
{{eqA}} : Eq A

open Ord {{...}} hiding (eqA)

Now anytime you have a function taking an Ord A argument the Eq A instance is also available by virtue of 𝜂-
expansion. So this works as you would expect:
_≤_ : {A : Set} {{OrdA : Ord A}} → A → A → Bool
x ≤ y = (x == y) || (x < y)

There is a problem however if you have multiple record arguments with conflicting instance fields. For instance,
suppose we also have a Num record with an Eq field
record Num (A : Set) : Set where
field
fromNat : Nat → A
{{eqA}} : Eq A

open Num {{...}} hiding (eqA)

_≤3 : {A : Set} {{OrdA : Ord A}} {{NumA : Num A}} → A → Bool


x ≤3 = (x == fromNat 3) || (x < fromNat 3)

Here the Eq A argument to _==_ is not resolved since there are two conflicting candidates: Ord.eqA OrdA and
Num.eqA NumA. To solve this problem you can declare instance fields as overlappable using the overlap keyword:
record Ord (A : Set) : Set where
field
_<_ : A → A → Bool
overlap {{eqA}} : Eq A

open Ord {{...}} hiding (eqA)

record Num (A : Set) : Set where


field
fromNat : Nat → A
overlap {{eqA}} : Eq A

open Num {{...}} hiding (eqA)

_≤3 : {A : Set} {{OrdA : Ord A}} {{NumA : Num A}} → A → Bool


x ≤3 = (x == fromNat 3) || (x < fromNat 3)

Whenever there are multiple valid candidates for an instance goal, if all candidates are overlappable, the goal is solved
by the left-most candidate. In the example above that means that the Eq A goal is solved by the instance from the
Ord argument.
Clauses for instance fields can be omitted when defining values of record types. For instance we can define Nat
instances for Eq, Ord and Num as follows, leaving out cases for the eqA fields:

3.31. Record Types 135


Agda User Manual, Release 2.6.2

instance
EqNat : Eq Nat
_==_ {{EqNat}} = Agda.Builtin.Nat._==_

OrdNat : Ord Nat


_<_ {{OrdNat}} = Agda.Builtin.Nat._<_

NumNat : Num Nat


fromNat {{NumNat}} n = n

3.32 Reflection

3.32.1 Builtin types

Names

The built-in QNAME type represents quoted names and comes equipped with equality, ordering, and a show function.

postulate Name : Set


{-# BUILTIN QNAME Name #-}

primitive
primQNameEquality : Name → Name → Bool
primQNameLess : Name → Name → Bool
primShowQName : Name → String

The fixity of a name can also be retrived.

primitive
primQNameFixity : Name → Fixity

To define a decidable propositional equality with the option --safe, one can use the conversion to a pair of built-in
64-bit machine words

primitive
primQNameToWord64s : Name → Σ Word64 (𝜆 _ → Word64)

with the injectivity proof in the Properties module.:

primitive
primQNameToWord64sInjective : ∀ a b → primQNameToWord64s a ≡ primQNameToWord64s b
˓→→ a ≡ b

Name literals are created using the quote keyword and can appear both in terms and in patterns

nameOfNat : Name
nameOfNat = quote Nat

isNat : Name → Bool


isNat (quote Nat) = true
isNat _ = false

Note that the name being quoted must be in scope.

136 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Metavariables

Metavariables are represented by the built-in AGDAMETA type. They have primitive equality, ordering, show, and
conversion to Nat:

postulate Meta : Set


{-# BUILTIN AGDAMETA Meta #-}

primitive
primMetaEquality : Meta → Meta → Bool
primMetaLess : Meta → Meta → Bool
primShowMeta : Meta → String
primMetaToNat : Meta → Nat

Builtin metavariables show up in reflected terms. In Properties, there is a proof of injectivity of


primMetaToNat

primitive
primMetaToNatInjective : ∀ a b → primMetaToNat a ≡ primMetaToNat b → a ≡ b

which can be used to define a decidable propositional equality with the option --safe.

Literals

Literals are mapped to the built-in AGDALITERAL datatype. Given the appropriate built-in binding for the types Nat,
Float, etc, the AGDALITERAL datatype has the following shape:

data Literal : Set where


nat : (n : Nat) → Literal
word64 : (n : Word64) → Literal
float : (x : Float) → Literal
char : (c : Char) → Literal
string : (s : String) → Literal
name : (x : Name) → Literal
meta : (x : Meta) → Literal

{-# BUILTIN AGDALITERAL Literal #-}


{-# BUILTIN AGDALITNAT nat #-}
{-# BUILTIN AGDALITWORD64 word64 #-}
{-# BUILTIN AGDALITFLOAT float #-}
{-# BUILTIN AGDALITCHAR char #-}
{-# BUILTIN AGDALITSTRING string #-}
{-# BUILTIN AGDALITQNAME name #-}
{-# BUILTIN AGDALITMETA meta #-}

Arguments

Arguments can be (visible), {hidden}, or {{instance}}:

data Visibility : Set where


visible hidden instance´ : Visibility

{-# BUILTIN HIDING Visibility #-}


{-# BUILTIN VISIBLE visible #-}
(continues on next page)

3.32. Reflection 137


Agda User Manual, Release 2.6.2

(continued from previous page)


{-# BUILTIN HIDDEN hidden #-}
{-# BUILTIN INSTANCE instance´ #-}

Arguments can be relevant or irrelevant:

data Relevance : Set where


relevant irrelevant : Relevance

{-# BUILTIN RELEVANCE Relevance #-}


{-# BUILTIN RELEVANT relevant #-}
{-# BUILTIN IRRELEVANT irrelevant #-}

Arguments also have a quantity:

data Quantity : Set where


quantity-0 quantity-𝜔 : Quantity

{-# BUILTIN QUANTITY Quantity #-}


{-# BUILTIN QUANTITY-0 quantity-0 #-}
{-# BUILTIN QUANTITY-𝜔 quantity-𝜔 #-}

Relevance and quantity are combined into a modality:

data Modality : Set where


modality : (r : Relevance) (q : Quantity) → Modality

{-# BUILTIN MODALITY Modality #-}


{-# BUILTIN MODALITY-CONSTRUCTOR modality #-}

The visibility and the modality characterise the behaviour of an argument:

data ArgInfo : Set where


arg-info : (v : Visibility) (m : Modality) → ArgInfo

data Arg (A : Set) : Set where


arg : (i : ArgInfo) (x : A) → Arg A

{-# BUILTIN ARGINFO ArgInfo #-}


{-# BUILTIN ARGARGINFO arg-info #-}
{-# BUILTIN ARG Arg #-}
{-# BUILTIN ARGARG arg #-}

Name abstraction

data Abs (A : Set) : Set where


abs : (s : String) (x : A) → Abs A

{-# BUILTIN ABS Abs #-}


{-# BUILTIN ABSABS abs #-}

Terms

Terms, sorts, patterns, and clauses are mutually recursive and mapped to the AGDATERM, AGDASORT,
AGDAPATTERN and AGDACLAUSE built-ins respectively. Types are simply terms. Terms and patterns use de Bruijn

138 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

indices to represent variables.

data Term : Set


data Sort : Set
data Pattern : Set
data Clause : Set
Type = Term
Telescope = List (Σ String 𝜆 _ → Arg Type)

data Term where


var : (x : Nat) (args : List (Arg Term)) → Term
con : (c : Name) (args : List (Arg Term)) → Term
def : (f : Name) (args : List (Arg Term)) → Term
lam : (v : Visibility) (t : Abs Term) → Term
pat-lam : (cs : List Clause) (args : List (Arg Term)) → Term
pi : (a : Arg Type) (b : Abs Type) → Term
agda-sort : (s : Sort) → Term
lit : (l : Literal) → Term
meta : (x : Meta) → List (Arg Term) → Term
unknown : Term -- Treated as '_' when unquoting.

data Sort where


set : (t : Term) → Sort -- A Set of a given (possibly neutral) level.
lit : (n : Nat) → Sort -- A Set of a given concrete level.
prop : (t : Term) → Sort -- A Prop of a given (possibly neutral) level.
propLit : (n : Nat) → Sort -- A Prop of a given concrete level.
inf : (n : Nat) → Sort -- Set𝜔i of a given concrete level i.
unknown : Sort

data Pattern where


con : (c : Name) (ps : List (Arg Pattern)) → Pattern
dot : (t : Term) → Pattern
var : (x : Nat ) → Pattern
lit : (l : Literal) → Pattern
proj : (f : Name) → Pattern
absurd : (x : Nat) → Pattern -- Absurd patterns have de Bruijn indices

data Clause where


clause : (tel : Telescope) (ps : List (Arg Pattern)) (t : Term) → Clause
absurd-clause : (tel : Telescope) (ps : List (Arg Pattern)) → Clause

{-# BUILTIN AGDATERM Term #-}


{-# BUILTIN AGDASORT Sort #-}
{-# BUILTIN AGDAPATTERN Pattern #-}
{-# BUILTIN AGDACLAUSE Clause #-}

{-# BUILTIN AGDATERMVAR var #-}


{-# BUILTIN AGDATERMCON con #-}
{-# BUILTIN AGDATERMDEF def #-}
{-# BUILTIN AGDATERMMETA meta #-}
{-# BUILTIN AGDATERMLAM lam #-}
{-# BUILTIN AGDATERMEXTLAM pat-lam #-}
{-# BUILTIN AGDATERMPI pi #-}
{-# BUILTIN AGDATERMSORT agda-sort #-}
{-# BUILTIN AGDATERMLIT lit #-}
{-# BUILTIN AGDATERMUNSUPPORTED unknown #-}

{-# BUILTIN AGDASORTSET set #-}


(continues on next page)

3.32. Reflection 139


Agda User Manual, Release 2.6.2

(continued from previous page)


{-# BUILTIN AGDASORTLIT lit #-}
{-# BUILTIN AGDASORTPROP prop #-}
{-# BUILTIN AGDASORTPROPLIT propLit #-}
{-# BUILTIN AGDASORTINF inf #-}
{-# BUILTIN AGDASORTUNSUPPORTED unknown #-}

{-# BUILTIN AGDAPATCON con #-}


{-# BUILTIN AGDAPATDOT dot #-}
{-# BUILTIN AGDAPATVAR var #-}
{-# BUILTIN AGDAPATLIT lit #-}
{-# BUILTIN AGDAPATPROJ proj #-}
{-# BUILTIN AGDAPATABSURD absurd #-}

{-# BUILTIN AGDACLAUSECLAUSE clause #-}


{-# BUILTIN AGDACLAUSEABSURD absurd-clause #-}

Absurd lambdas 𝜆 () are quoted to extended lambdas with an absurd clause.


The built-in constructors AGDATERMUNSUPPORTED and AGDASORTUNSUPPORTED are translated to meta variables
when unquoting.

Declarations

There is a built-in type AGDADEFINITION representing definitions. Values of this type is returned by the
AGDATCMGETDEFINITION built-in described below.

data Definition : Set where


function : (cs : List Clause) → Definition
data-type : (pars : Nat) (cs : List Name) → Definition -- parameters and
˓→constructors

record-type : (c : Name) (fs : List (Arg Name)) → -- c: name of record


˓→constructor

Definition -- fs: fields


data-cons : (d : Name) → Definition -- d: name of data type
axiom : Definition
prim-fun : Definition

{-# BUILTIN AGDADEFINITION Definition #-}


{-# BUILTIN AGDADEFINITIONFUNDEF function #-}
{-# BUILTIN AGDADEFINITIONDATADEF data-type #-}
{-# BUILTIN AGDADEFINITIONRECORDDEF record-type #-}
{-# BUILTIN AGDADEFINITIONDATACONSTRUCTOR data-cons #-}
{-# BUILTIN AGDADEFINITIONPOSTULATE axiom #-}
{-# BUILTIN AGDADEFINITIONPRIMITIVE prim-fun #-}

Type errors

Type checking computations (see below) can fail with an error, which is a list of ErrorParts. This allows metapro-
grams to generate nice errors without having to implement pretty printing for reflected terms.

-- Error messages can contain embedded names and terms.


data ErrorPart : Set where
strErr : String → ErrorPart
termErr : Term → ErrorPart
(continues on next page)

140 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


nameErr : Name → ErrorPart

{-# BUILTIN AGDAERRORPART ErrorPart #-}


{-# BUILTIN AGDAERRORPARTSTRING strErr #-}
{-# BUILTIN AGDAERRORPARTTERM termErr #-}
{-# BUILTIN AGDAERRORPARTNAME nameErr #-}

Type checking computations

Metaprograms, i.e. programs that create other programs, run in a built-in type checking monad TC:

postulate
TC : ∀ {a} → Set a → Set a
returnTC : ∀ {a} {A : Set a} → A → TC A
bindTC : ∀ {a b} {A : Set a} {B : Set b} → TC A → (A → TC B) → TC B

{-# BUILTIN AGDATCM TC #-}


{-# BUILTIN AGDATCMRETURN returnTC #-}
{-# BUILTIN AGDATCMBIND bindTC #-}

The TC monad provides an interface to the Agda type checker using the following primitive operations:

postulate
-- Unify two terms, potentially solving metavariables in the process.
unify : Term → Term → TC ⊤

-- Throw a type error. Can be caught by catchTC.


typeError : ∀ {a} {A : Set a} → List ErrorPart → TC A

-- Block a type checking computation on a metavariable. This will abort


-- the computation and restart it (from the beginning) when the
-- metavariable is solved.
blockOnMeta : ∀ {a} {A : Set a} → Meta → TC A

-- Prevent current solutions of metavariables from being rolled back in


-- case 'blockOnMeta' is called.
commitTC : TC ⊤

-- Backtrack and try the second argument if the first argument throws a
-- type error.
catchTC : ∀ {a} {A : Set a} → TC A → TC A → TC A

-- Infer the type of a given term


inferType : Term → TC Type

-- Check a term against a given type. This may resolve implicit arguments
-- in the term, so a new refined term is returned. Can be used to create
-- new metavariables: newMeta t = checkType unknown t
checkType : Term → Type → TC Term

-- Compute the normal form of a term.


normalise : Term → TC Term

-- Compute the weak head normal form of a term.


reduce : Term → TC Term
(continues on next page)

3.32. Reflection 141


Agda User Manual, Release 2.6.2

(continued from previous page)

-- Get the current context. Returns the context in reverse order, so that
-- it is indexable by deBruijn index. Note that the types in the context are
-- valid in the rest of the context. To use in the current context they need
-- to be weakened by 1 + their position in the list.
getContext : TC (List (Arg Type))

-- Extend the current context with a variable of the given type.


extendContext : ∀ {a} {A : Set a} → Arg Type → TC A → TC A

-- Set the current context. Takes a context telescope entries in


-- reverse order, as given by `getContext`. Each type should be valid
-- in the context formed by the remaining elements in the list.
inContext : ∀ {a} {A : Set a} → List (Arg Type) → TC A → TC A

-- Quote a value, returning the corresponding Term.


quoteTC : ∀ {a} {A : Set a} → A → TC Term

-- Unquote a Term, returning the corresponding value.


unquoteTC : ∀ {a} {A : Set a} → Term → TC A

-- Quote a value in Set𝜔, returning the corresponding Term


quote𝜔TC : ∀ {A : Set𝜔} → A → TC Term

-- Create a fresh name.


freshName : String → TC Name

-- Declare a new function of the given type. The function must be defined
-- later using 'defineFun'. Takes an Arg Name to allow declaring instances
-- and irrelevant functions. The Visibility of the Arg must not be hidden.
declareDef : Arg Name → Type → TC ⊤

-- Declare a new postulate of the given type. The Visibility of the Arg
-- must not be hidden. It fails when executed from command-line with --safe
-- option.
declarePostulate : Arg Name → Type → TC ⊤

-- Define a declared function. The function may have been declared using
-- 'declareDef' or with an explicit type signature in the program.
defineFun : Name → List Clause → TC ⊤

-- Get the type of a defined name. Replaces 'primNameType'.


getType : Name → TC Type

-- Get the definition of a defined name. Replaces 'primNameDefinition'.


getDefinition : Name → TC Definition

-- Check if a name refers to a macro


isMacro : Name → TC Bool

-- Change the behaviour of inferType, checkType, quoteTC, getContext


-- to normalise (or not) their results. The default behaviour is no
-- normalisation.
withNormalisation : ∀ {a} {A : Set a} → Bool → TC A → TC A

-- Prints the third argument to the debug buffer in Emacs


-- if the verbosity level (set by the -v flag to Agda)
(continues on next page)

142 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(continued from previous page)


-- is higher than the second argument. Note that Level 0 and 1 are printed
-- to the info buffer instead. For instance, giving -v a.b.c:10 enables
-- printing from debugPrint "a.b.c.d" 10 msg.
debugPrint : String → Nat → List ErrorPart → TC ⊤

-- Only allow reduction of specific definitions while executing the TC computation


onlyReduceDefs : ∀ {a} {A : Set a} → List Name → TC A → TC A

-- Don't allow reduction of specific definitions while executing the TC computation


dontReduceDefs : ∀ {a} {A : Set a} → List Name → TC A → TC A

-- Makes the following primitives to reconstruct hidden parameters:


-- getDefinition, normalise, reduce, inferType, checkType and getContext
withReconstructed : ∀ {a} {A : Set a} → TC A → TC A

-- Fail if the given computation gives rise to new, unsolved


-- "blocking" constraints.
noConstraints : ∀ {a} {A : Set a} → TC A → TC A

-- Run the given TC action and return the first component. Resets to
-- the old TC state if the second component is 'false', or keep the
-- new TC state if it is 'true'.
runSpeculative : ∀ {a} {A : Set a} → TC (Σ A 𝜆 _ → Bool) → TC A

{-# BUILTIN AGDATCMUNIFY unify #-}


{-# BUILTIN AGDATCMTYPEERROR typeError #-}
{-# BUILTIN AGDATCMBLOCKONMETA blockOnMeta #-}
{-# BUILTIN AGDATCMCATCHERROR catchTC #-}
{-# BUILTIN AGDATCMINFERTYPE inferType #-}
{-# BUILTIN AGDATCMCHECKTYPE checkType #-}
{-# BUILTIN AGDATCMNORMALISE normalise #-}
{-# BUILTIN AGDATCMREDUCE reduce #-}
{-# BUILTIN AGDATCMGETCONTEXT getContext #-}
{-# BUILTIN AGDATCMEXTENDCONTEXT extendContext #-}
{-# BUILTIN AGDATCMINCONTEXT inContext #-}
{-# BUILTIN AGDATCMQUOTETERM quoteTC #-}
{-# BUILTIN AGDATCMUNQUOTETERM unquoteTC #-}
{-# BUILTIN AGDATCMQUOTEOMEGATERM quote𝜔TC #-}
{-# BUILTIN AGDATCMFRESHNAME freshName #-}
{-# BUILTIN AGDATCMDECLAREDEF declareDef #-}
{-# BUILTIN AGDATCMDECLAREPOSTULATE declarePostulate #-}
{-# BUILTIN AGDATCMDEFINEFUN defineFun #-}
{-# BUILTIN AGDATCMGETTYPE getType #-}
{-# BUILTIN AGDATCMGETDEFINITION getDefinition #-}
{-# BUILTIN AGDATCMCOMMIT commitTC #-}
{-# BUILTIN AGDATCMISMACRO isMacro #-}
{-# BUILTIN AGDATCMWITHNORMALISATION withNormalisation #-}
{-# BUILTIN AGDATCMDEBUGPRINT debugPrint #-}
{-# BUILTIN AGDATCMONLYREDUCEDEFS onlyReduceDefs #-}
{-# BUILTIN AGDATCMDONTREDUCEDEFS dontReduceDefs #-}
{-# BUILTIN AGDATCMNOCONSTRAINTS noConstraints #-}
{-# BUILTIN AGDATCMRUNSPECULATIVE runSpeculative #-}

3.32. Reflection 143


Agda User Manual, Release 2.6.2

3.32.2 Metaprogramming

There are three ways to run a metaprogram (TC computation). To run a metaprogram in a term position you use
a macro. To run metaprograms to create top-level definitions you can use the unquoteDecl and unquoteDef
primitives (see Unquoting Declarations).

Macros

Macros are functions of type t1 → t2 → .. → Term → TC ⊤ that are defined in a macro block. The last
argument is supplied by the type checker and will be the representation of a metavariable that should be instantiated
with the result of the macro.
Macro application is guided by the type of the macro, where Term and Name arguments are quoted before passed to
the macro. Arguments of any other type are preserved as-is.
For example, the macro application f u v w where f : Term → Name → Bool → Term → TC ⊤
desugars into:

unquote (f (quoteTerm u) (quote v) w)

where quoteTerm u takes a u of arbitrary type and returns its representation in the Term data type, and unquote
m runs a computation in the TC monad. Specifically, when checking unquote m : A for some type A the type
checker proceeds as follows:
• Check m : Term → TC ⊤.
• Create a fresh metavariable hole : A.
• Let qhole : Term be the quoted representation of hole.
• Execute m qhole.
• Return (the now hopefully instantiated) hole.
Reflected macro calls are constructed using the def constructor, so given a macro g : Term → TC ⊤ the term
def (quote g) [] unquotes to a macro call to g.

Note: The quoteTerm and unquote primitives are available in the language, but it is recommended to avoid using
them in favour of macros.

Limitations:
• Macros cannot be recursive. This can be worked around by defining the recursive function outside the macro
block and have the macro call the recursive function.
Silly example:

macro
plus-to-times : Term → Term → TC ⊤
plus-to-times (def (quote _+_) (a :: b :: [])) hole =
unify hole (def (quote _*_) (a :: b :: []))
plus-to-times v hole = unify hole v

thm : (a b : Nat) → plus-to-times (a + b) ≡ a * b


thm a b = refl

Macros lets you write tactics that can be applied without any syntactic overhead. For instance, suppose you have a
solver:

144 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

magic : Type → Term

that takes a reflected goal and outputs a proof (when successful). You can then define the following macro:

macro
by-magic : Term → TC ⊤
by-magic hole =
bindTC (inferType hole) 𝜆 goal →
unify hole (magic goal)

This lets you apply the magic tactic as a normal function:

thm : ¬ P ≡ NP
thm = by-magic

Tactic Arguments

You can declare tactics to be used to solve a particular implicit argument using a @(tactic t) annotation. The
provided tactic should be a term t : Term → TC ⊤. For instance,

defaultTo : {A : Set} (x : A) → Term → TC ⊤


defaultTo x hole = bindTC (quoteTC x) (unify hole)

f : {@(tactic defaultTo true) x : Bool} → Bool


f {x} = x

test-f : f ≡ true
test-f = refl

At calls to f, defaultTo true is called on the metavariable inserted for x if it is not given explicitly. The tactic can depend
on previous arguments to the function. For instance,

g : (x : Nat) {@(tactic defaultTo x) y : Nat} → Nat


g x {y} = x + y

test-g : g 4 ≡ 8
test-g = refl

Record fields can also be annotated with a tactic, allowing them to be omitted in constructor applications, record
constructions and co-pattern matches:

record Bools : Set where


constructor mkBools
field fst : Bool
@(tactic defaultTo fst) {snd} : Bool
open Bools

tt0 tt1 tt2 tt3 : Bools


tt0 = mkBools true {true}
tt1 = mkBools true
tt2 = record{ fst = true }
tt3 .fst = true

test-tt : tt1 :: tt2 :: tt3 :: [] ≡ tt0 :: tt0 :: tt0 :: []


test-tt = refl

3.32. Reflection 145


Agda User Manual, Release 2.6.2

Unquoting Declarations

While macros let you write metaprograms to create terms, it is also useful to be able to create top-level definitions.
You can do this from a macro using the declareDef and defineFun primitives, but there is no way to bring such
definitions into scope. For this purpose there are two top-level primitives unquoteDecl and unquoteDef that
runs a TC computation in a declaration position. They both have the same form:

unquoteDecl x1 .. x𝑛 = m
unquoteDef x1 .. x𝑛 = m

except that the list of names can be empty for unquoteDecl, but not for unquoteDef. In both cases m should
have type TC ⊤. The main difference between the two is that unquoteDecl requires m to both declare (with
declareDef) and define (with defineFun) the x𝑖 whereas unquoteDef expects the x𝑖 to be already declared.
In other words, unquoteDecl brings the x𝑖 into scope, but unquoteDef requires them to already be in scope.
In m the x𝑖 stand for the names of the functions being defined (i.e. x𝑖 : Name) rather than the actual functions.
One advantage of unquoteDef over unquoteDecl is that unquoteDef is allowed in mutual blocks, allowing
mutually recursion between generated definitions and hand-written definitions.
Example usage:

arg´ : {A : Set} → Visibility → A → Arg A


arg´ v = arg (arg-info v (modality relevant quantity-𝜔))

-- Defining: id-name {A} x = x


defId : (id-name : Name) → TC ⊤
defId id-name = do
defineFun id-name
[ clause
( ("A" , arg´ visible (agda-sort (lit 0)))
:: ("x" , arg´ visible (var 0 []))
:: [])
( arg´ hidden (var 1)
:: arg´ visible (var 0)
:: [] )
(var 0 [])
]

id : {A : Set} (x : A) → A
unquoteDef id = defId id

mkId : (id-name : Name) → TC ⊤


mkId id-name = do
ty ← quoteTC ({A : Set} (x : A) → A)
declareDef (arg´ visible id-name) ty
defId id-name

unquoteDecl id´ = mkId id´

System Calls

It is possible to run system calls as part of a metaprogram, using the execTC builtin. You can use this feature to
implement type providers, or to call external solvers. For instance, the following example calls /bin/echo from
Agda:

146 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

postulate
execTC : (exe : String) (args : List String) (stdIn : String)
→ TC (Σ Nat (𝜆 _ → Σ String (𝜆 _ → String)))

{-# BUILTIN AGDATCMEXEC execTC #-}

macro
echo : List String → Term → TC ⊤
echo args hole = do
(exitCode , (stdOut , stdErr)) ← execTC "echo" args ""
unify hole (lit (string stdOut))

_ : echo ("hello" :: "world" :: []) ≡ "hello world\n"


_ = refl

The execTC builtin takes three arguments: the basename of the executable (e.g., "echo"), a list of arguments, and
the contents of the standard input. It returns a triple, consisting of the exit code (as a natural number), the contents of
the standard output, and the contents of the standard error.
It would be ill-advised to allow Agda to make arbitrary system calls. Hence, the feature must be activated by passing
the --allow-exec option, either on the command-line or using a pragma. (Note that --allow-exec is incom-
patible with --safe.) Furthermore, Agda can only call executables which are listed in the list of trusted executables,
~/.agda/executables. For instance, to run the example above, you must add /bin/echo to this file:

# contents of ~/.agda/executables
/bin/echo

The executable can then be called by passing its basename to execTC, subtracting the .exe on Windows.

3.33 Rewriting

Rewrite rules allow you to extend Agda’s evaluation relation with new computation rules.

Note: This page is about the --rewriting option and the associated REWRITE builtin. You might be looking for
the documentation on the rewrite construct instead.

3.33.1 Rewrite rules by example

To enable rewrite rules, you should run Agda with the flag --rewriting and import the modules Agda.
Builtin.Equality and Agda.Builtin.Equality.Rewrite:

{-# OPTIONS --rewriting #-}

module language.rewriting where

open import Agda.Builtin.Equality


open import Agda.Builtin.Equality.Rewrite

3.33. Rewriting 147


Agda User Manual, Release 2.6.2

Overlapping pattern matching

To start, let’s look at an example where rewrite rules can solve a problem that is encountered by almost every new-
comer to Agda. This problem usually pops up as the question why 0 + m computes to m, but m + 0 does not (and
similarly, (suc m) + n computes to suc (m + n) but m + (suc n) does not). This problem manifests itself
for example when trying to prove commutativity of _+_:

+comm : m + n ≡ n + m
+comm {m = zero} = refl
+comm {m = suc m} = cong suc (+comm {m = m})

Here, Agda complains that n != n + zero of type Nat. The usual way to solve this problem is by proving
the equations m + 0 ≡ m and m + (suc n) ≡ suc (m + n) and using an explicit rewrite statement in
the main proof (N.B.: Agda’s rewrite keyword should not be confused with rewrite rules, which are added by a
REWRITE pragma.)
By using rewrite rules, we can simulate the solution from our paper. First, we need to prove that the equations we want
hold as propositional equalities:

+zero : m + zero ≡ m
+zero {m = zero} = refl
+zero {m = suc m} = cong suc +zero

+suc : m + (suc n) ≡ suc (m + n)


+suc {m = zero} = refl
+suc {m = suc m} = cong suc +suc

Next we mark the equalities as rewrite rules with a REWRITE pragma:

{-# REWRITE +zero +suc #-}

Now the proof of commutativity works exactly as we wrote it before:

+comm : m + n ≡ n + m
+comm {m = zero} = refl
+comm {m = suc m} = cong suc (+comm {m = m})

Note that there is no way to make this proof go through without rewrite rules: it is essential that _+_ computes both
on its first and its second argument, but there’s no way to define _+_ in such a way using Agda’s regular pattern
matching.

More examples

Additional examples of how to use rewrite rules can be found in a blog post by Jesper Cockx.

3.33.2 General shape of rewrite rules

In general, an equality proof eq may be registered as a rewrite rule using the pragma {-# REWRITE eq #-},
provided the following requirements are met:
• The type of eq is of the form eq : (x1 : A1 ) ... (x𝑘 : A𝑘 ) → f p1 ... p𝑛 ≡ v
• f is a postulate, a defined function symbol, or a constructor applied to fully general parameters (i.e. the param-
eters must be distinct variables)

148 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• Each variable x1 , . . . , x𝑘 occurs at least once in a pattern position in p1 ... p𝑛 (see below for the definition
of pattern positions)
• The left-hand side f p1 ... p𝑛 should be neutral, i.e. it should not reduce.
The following patterns are supported:
• x y1 ... y𝑛 , where x is a pattern variable and y1 , . . . , y𝑛 are distinct variables that are bound locally in the
pattern
• f p1 ... p𝑛 , where f is a postulate, a defined function, a constructor, or a data/record type, and p1 , . . . , p𝑛
are again patterns
• 𝜆 x → p, where p is again a pattern
• (x : P) → Q, where P and Q are again patterns
• y p1 ... p𝑛 , where y is a variable bound locally in the pattern and p1 , . . . , p𝑛 are again patterns
• Set p or Prop p, where p is again a pattern
• Any other term v (here the variables in v are not considered to be in a pattern position)
Once a rewrite rule has been added, Agda automatically rewrites all instances of the left-hand side to the corresponding
instance of the right-hand side during reduction. More precisely, a term (definitionally equal to) f p1 𝜎 ... p𝑛 𝜎 is
rewritten to v𝜎, where 𝜎 is any substitution on the pattern variables x1 , . . . x𝑘 .
Since rewriting happens after normal reduction, rewrite rules are only applied to terms that would otherwise be neutral.

3.33.3 Confluence checking

Agda can optionally check confluence of rewrite rules by enabling the --confluence-check flag. Concretely, it
does so by enforcing two properties:
1. For any two left-hand sides of the rewrite rules that overlap (either at the root position or at a subterm), the most
general unifier of the two left-hand sides is again a left-hand side of a rewrite rule. For example, if there are two
rules suc m + n = suc (m + n) and m + suc n = suc (m + n), then there should also be a rule
suc m + suc n = suc (suc (m + n)).
2. Each rewrite rule should satisfy the triangle property: For any rewrite rule u = w and any single-step parallel
unfolding u => v, we should have another single-step parallel unfolding v => w.
There is also a flag --local-confluence-check that is less restrictive but only checks local confluence of
rewrite rules. In case the rewrite rules are terminating (currently not checked), these two properties are equivalent.

3.33.4 Advanced usage

Instead of importing Agda.Builtin.Equality.Rewrite, a different type may be chosen as the rewrite relation
by registering it as the REWRITE builtin. For example, using the pragma {-# BUILTIN REWRITE _~_ #-}
registers the type _~_ as the rewrite relation. To qualify as the rewrite relation, the type must take at least two
arguments, and the final two arguments should be visible.

3.34 Run-time Irrelevance

From version 2.6.1 Agda supports run-time irrelevance (or erasure) annotations. Values marked as erased are not
present at run time, and consequently the type checker enforces that no computations depend on erased values.

3.34. Run-time Irrelevance 149


Agda User Manual, Release 2.6.2

3.34.1 Syntax

A function or constructor argument is declared erased using the @0 or @erased annotation. For example, the follow-
ing definition of vectors guarantees that the length argument to _::_ is not present at runtime:

data Vec (A : Set a) : @0 Nat → Set a where


[] : Vec A 0
_::_ : ∀ {@0 n} → A → Vec A n → Vec A (suc n)

The GHC backend compiles this to a datatype where the cons constructor takes only two arguments.

Note: In this particular case, the compiler identifies that the length argument can be erased also without the annotation,
using Brady et al’s forcing analysis [1]. Marking it erased explictly, however, ensures that it is erased without relying
on the analysis.

Erasure annotations can also appear in function arguments (both first-order and higher-order). For instance, here is an
implementation of foldl on vectors:

foldl : (B : Nat → Set b)


→ (f : ∀ {@0 n} → B n → A → B (suc n))
→ (z : B 0)
→ ∀ {@0 n} → Vec A n → B n
foldl B f z [] = z
foldl B f z (x :: xs) = foldl (𝜆 n → B (suc n)) (𝜆 {n} → f {suc n}) (f z x) xs

Here the length arguments to foldl and to f have been marked erased. As a result it gets compiled to the following
Haskell code (modulo renaming):

foldl f z xs
= case xs of
[] -> z
x :: xs -> foldl f (f _ z x) xs

In contrast to constructor arguments, erased arguments to higher-order functions are not removed completely, but
instead replaced by a placeholder value _. The crucial optimization enabled by the erasure annotation is compiling
𝜆 {n} → f {suc n} to simply f, removing a terrible space leak from the program. Compare to the result of
compiling without erasure:

foldl f z xs
= case xs of
[] -> z
x :: xs -> foldl (\ n -> f (1 + n)) (f 0 z x) xs

It is also possible to mark top-level definitions as erased. This guarantees that they are only used in erased arguments
and can be useful to ensure that code intended only for compile-time evaluation is not executed at run time. (One can
also use erased things in the bodies of erased definitions.) For instance,

@0 spec : Nat → Nat -- slow, but easy to verify


impl : Nat → Nat -- fast, but hard to understand
proof : ∀ n → spec n ≡ impl n

Erased record fields become erased arguments to the record constructor and the projection functions are treated as
erased definitions.
Constructors can also be marked as erased. Here is one example:

150 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Is-proposition : Set a → Set a


Is-proposition A = (x y : A) → x ≡ y

data ‖_‖ (A : Set a) : Set a where


|_| : A → ‖ A ‖
@0 trivial : Is-proposition ‖ A ‖

rec : @0 Is-proposition B → (A → B) → ‖ A ‖ → B
rec p f | x | = f x
rec p f (trivial x y i) = p (rec p f x) (rec p f y) i

In the code above the constructor trivial is only available at compile-time, whereas |_| is also available at run-time.
Clauses that match on erased constructors in non-erased positions are omitted by (at least some) compiler backends,
so one can use erased names in the bodies of such clauses.

3.34.2 Rules

The typing rules are based on Conor McBride’s “I Got Plenty o’Nuttin’” [2] and Bob Atkey’s “The Syntax and
Semantics of Quantitative Type Theory” [3]. In essence the type checker keeps track of whether it is running in run-
time mode, checking something that is needed at run time, or compile-time mode, checking something that will be
erased. In compile-time mode everything to do with erasure can safely be ignored, but in run-time mode the following
restrictions apply:
• Cannot use erased variables or definitions.
• Cannot pattern match on erased arguments, unless there is at most one valid case (not counting erased construc-
tors). If --without-K is enabled and there is one valid case, then the datatype must also not be indexed.
Consider the function foo taking an erased vector argument:

foo : (n : Nat) (@0 xs : Vec Nat n) → Nat


foo zero [] = 0
foo (suc n) (x :: xs) = foo n xs

This is okay (when the K rule is on), since after matching on the length, the matching on the vector does not provide
any computational information, and any variables in the pattern (x and xs in this case) are marked erased in turn. On
the other hand, if we don’t match on the length first, the type checker complains:

foo : (n : Nat) (@0 xs : Vec Nat n) → Nat


foo n [] = 0
foo n (x :: xs) = foo _ xs
-- Error: Cannot branch on erased argument of datatype Vec Nat n

The type checker enters compile-time mode when


• checking erased arguments to a constructor or function,
• checking the body of an erased definition,
• checking the body of a clause that matches on an erased constructor,
• checking the domain of an erased Π type, or
• checking a type, i.e. when moving to the right of a :, with some exceptions:
– Compile-time mode is not entered for the domains of non-erased Π types.
– If the K rule is off then compile-time mode is not entered for non-erased constructors (of fibrant type) or
record fields.

3.34. Run-time Irrelevance 151


Agda User Manual, Release 2.6.2

Note that the type checker does not enter compile-time mode based on the type a term is checked against (except that
a distinction is sometimes made between fibrant and non-fibrant types). In particular, checking a term against Set
does not trigger compile-time mode.

3.34.3 Subtyping of runtime-irrelevant function spaces

Normally, if f : (@0 x : A) → B then we have 𝜆 x → f x : (x : A) → B but not f : (x


: A) → B. When the option --subtyping is enabled, Agda will make use of the subtyping rule (@0 x :
A) → B <: (x : A) → B, so there is no need for eta-expanding the function f.

3.34.4 References

[1] Brady, Edwin, Conor McBride, and James McKinna. “Inductive Families Need Not Store Their Indices.” Interna-
tional Workshop on Types for Proofs and Programs. Springer, Berlin, Heidelberg, 2003.
[2] McBride, Conor. “I Got Plenty o’Nuttin’.” A List of Successes That Can Change the World. Springer, Cham,
2016.
[3] Atkey, Robert. “The Syntax and Semantics of Quantitative Type Theory”. In LICS ‘18: Oxford, United Kingdom.
2018.

3.35 Safe Agda

By using the option --safe (as a pragma option, or on the command-line), a user can specify that Agda should
ensure that features leading to possible inconsistencies should be disabled.
Here is a list of the features --safe is incompatible with:
• postulate; can be used to assume any axiom.
• --allow-unsolved-metas; forces Agda to accept unfinished proofs.
• --allow-incomplete-matches; forces Agda to accept unfinished proofs.
• --no-positivity-check; makes it possible to write non-terminating programs by structural “induction”
on non strictly positive datatypes.
• --no-termination-check; gives loopy programs any type.
• --type-in-type and --omega-in-omega; allow the user to encode the Girard-Hurken paradox.
• --injective-type-constructors; together with excluded middle leads to an inconsistency via Chung-
Kil Hur’s construction.
• --guardedness together with --sized-types; currently can be used to define a type which is both
inductive and coinductive, which leads to an inconsistency. This might be fixed in the future.
• --experimental-irrelevance and --irrelevant-projections; enables potentially unsound ir-
relevance features (irrelevant levels, irrelevant data matching, and projection of irrelevant record fields, respec-
tively).
• --rewriting; turns any equation into one that holds definitionally. It can at the very least break convergence.
• --cubical together with --with-K; the univalence axiom is provable using cubical constructions, which
falsifies the K axiom.
• The primEraseEquality primitive together with --without-K; using primEraseEquality, one
can derive the K axiom.

152 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• --allow-exec; allows system calls during type checking.


The option --safe is coinfective (see Consistency checking of options used); if a module is declared safe, then all its
imported modules must also be declared safe.

Note: The --guardedness and --sized-types options are both on by default. However, unless they have
been set explicitly by the user, setting the --safe option will turn them both off. That is to say that

{-# OPTIONS --safe #-}

will correspond to --safe, --no-guardedness, and --no-sized-types. When both

{-# OPTIONS --safe --guardedness #-}

and

{-# OPTIONS --guardedness --safe #-}

will turn on --safe, --guardedness, and --no-sized-types.


Setting both --sized-types and --guardedness whilst demanding that the module is --safe will lead to an
error as combining these options currently is inconsistent.

3.36 Sized Types

Note: This is a stub.

Sizes help the termination checker by tracking the depth of data structures across definition boundaries.
The built-in combinators for sizes are described in Sized types.

3.36.1 Example for coinduction: finite languages

See Abel 2017 and Traytel 2017.


Decidable languages can be represented as infinite trees. Each node has as many children as the number of characters
in the alphabet A. Each path from the root of the tree to a node determines a possible word in the language. Each node
has a boolean label, which is true if and only if the word corresponding to that node is in the language. In particular,
the root node of the tree is labelled true if and only if the word 𝜖 belongs to the language.
These infinite trees can be represented as the following coinductive data-type:

record Lang (i : Size) (A : Set) : Set where


coinductive
field
𝜈 : Bool
𝛿 : ∀{j : Size< i} → A → Lang j A

open Lang

As we said before, given a language a : Lang A, 𝜈 a ≡ true iff 𝜖 ∈ a. On the other hand, the language 𝛿
a x : Lang A is the Brzozowski derivative of a with respect to the character x, that is, w ∈ 𝛿 a x iff xw ∈
a.

3.36. Sized Types 153


Agda User Manual, Release 2.6.2

With this data type, we can define some regular languages. The first one, the empty language, contains no words; so
all the nodes are labelled false:

∅ : ∀ {i A} → Lang i A
𝜈 ∅ = false
𝛿 ∅ _ = ∅

The second one is the language containing a single word; the empty word. The root node is labelled true, and all the
others are labelled false:

𝜖 : ∀ {i A} → Lang i A
𝜈 𝜖 = true
𝛿 𝜖 _ = ∅

To compute the union (or sum) of two languages, we do a point-wise or operation on the labels of their nodes:

_+_ : ∀ {i A} → Lang i A → Lang i A → Lang i A


𝜈 (a + b) = 𝜈 a ∨ 𝜈 b
𝛿 (a + b) x = 𝛿 a x + 𝛿 b x

infixl 10 _+_

Now, lets define concatenation. The base case (𝜈) is straightforward: 𝜖 ∈ a · b iff 𝜖 ∈ a and 𝜖 ∈ b.
For the derivative (𝛿), assume that we have a word w, w ∈ 𝛿 (a · b) x. This means that xw = 𝛼𝛽, with 𝛼 ∈ a
and 𝛽 ∈ b.
We have to consider two cases:
1. 𝜖 ∈ a. Then, either:
• 𝛼 = 𝜖, and 𝛽 = xw, where w ∈ 𝛿 b x.
• 𝛼 = x𝛼’, with 𝛼’ ∈ 𝛿 a x, and w = 𝛼’𝛽 ∈ 𝛿 a x · b.
2. 𝜖 ̸∈ a. Then, only the second case above is possible:
• 𝛼 = x𝛼’, with 𝛼’ ∈ 𝛿 a x, and w = 𝛼’𝛽 ∈ 𝛿 a x · b.

_·_ : ∀ {i A} → Lang i A → Lang i A → Lang i A


𝜈 (a · b) = 𝜈 a ∧ 𝜈 b
𝛿 (a · b) x = if 𝜈 a then 𝛿 a x · b + 𝛿 b x else 𝛿 a x · b

infixl 20 _·_

Here is where sized types really shine. Without sized types, the termination checker would not be able to recognize that
_+_ or if_then_else are not inspecting the tree, which could render the definition non-productive. By contrast,
with sized types, we know that the a + b is defined to the same depth as a and b are.
In a similar spirit, we can define the Kleene star:

_* : ∀ {i A} → Lang i A → Lang i A
𝜈 (a *) = true
𝛿 (a *) x = 𝛿 a x · a *

infixl 30 _*

Again, because the types tell us that _·_ preserves the size of its inputs, we can have the recursive call to a * under a
function call to _·_.

154 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Testing

First, we want to give a precise notion of membership in a language. We consider a word as a List of characters.
_∈_ : ∀ {i} {A} → List i A → Lang i A → Bool
[] ∈ a = 𝜈 a
(x :: w) ∈ a = w ∈ 𝛿 a x

Note how the size of the word we test for membership cannot be larger than the depth to which the language tree is
defined.
If we want to use regular, non-sized lists, we need to ask for the language to have size ∞.
_∈_ : ∀ {A} → List A → Lang ∞ A → Bool
[] ∈ a = 𝜈 a
(x :: w) ∈ a = w ∈ 𝛿 a x

Intuitively, ∞ is a Size larger than the size of any term than one could possibly define in Agda.
Now, let’s consider binary strings as words. First, we define the languages J x K containing the single word “x” of
length 1, for alphabet A = Bool:
J_K : ∀ {i} → Bool → Lang i Bool
𝜈 J _ K = false

𝛿 J false K false = 𝜖
𝛿 J true K true = 𝜖
𝛿 J false K true = ∅
𝛿 J true K false = ∅

Now we can define the bip-bop language, consisting of strings of even length alternating letters “true” and “false”.
bip-bop = (J true K · J false K)*

Let’s test a few words for membership in the language bip-bop!


test1 : (true :: false :: true :: false :: true :: false :: []) ∈ bip-bop ≡ true
test1 = refl

test2 : (true :: false :: true :: false :: true :: []) ∈ bip-bop ≡ false


test2 = refl

test3 : (true :: true :: false :: []) ∈ bip-bop ≡ false


test3 = refl

3.36.2 References

Equational Reasoning about Formal Languages in Coalgebraic Style, Andreas Abel.


Formal Languages, Formally and Coinductively, Dmitriy Traytel, LMCS Vol. 13(3:28)2017, pp. 1–22
(2017).

3.37 Sort System

Sorts (also known as universes) are types whose members themselves are again types. The fundamental sort in Agda
is named Set and it denotes the universe of small types. But for some applications, other sorts are needed. This page

3.37. Sort System 155


Agda User Manual, Release 2.6.2

explains the need for additional sorts and describes all the sorts that are used by Agda.

3.37.1 Introduction to universes

Russell’s paradox implies that the collection of all sets is not itself a set. Namely, if there were such a set U, then one
could form the subset A ⊆ U of all sets that do not contain themselves. Then we would have A ∈ A if and only if A
̸∈ A, a contradiction.
Likewise, Martin-Löf’s type theory had originally a rule Set : Set but Girard showed that it is inconsistent. This
result is known as Girard’s paradox. Hence, not every Agda type is a Set. For example, we have

Bool : Set
Nat : Set

but not Set : Set. However, it is often convenient for Set to have a type of its own, and so in Agda, it is given
the type Set1 :

Set : Set1

In many ways, expressions of type Set1 behave just like expressions of type Set; for example, they can be used as
types of other things. However, the elements of Set1 are potentially larger; when A : Set1 , then A is sometimes
called a large set. In turn, we have

Set1 : Set2
Set2 : Set3

and so on. A type whose elements are types is called a sort or a universe; Agda provides an infinite number of
universes Set, Set1 , Set2 , Set3 , . . . , each of which is an element of the next one. In fact, Set itself is just an
abbreviation for Set0 . The subscript n is called the level of the universe Set𝑛 .

Note: You can also write Set1, Set2, etc., instead of Set1 , Set2 . To enter a subscript in the Emacs mode, type
“\_1”.

Universe example

So why are universes useful? Because sometimes it is necessary to define, and prove theorems about, functions that
operate not just on sets but on large sets. In fact, most Agda users sooner or later experience an error message where
Agda complains that Set1 != Set. These errors usually mean that a small set was used where a large one was
expected, or vice versa.
For example, suppose you have defined the usual datatypes for lists and cartesian products:

data List (A : Set) : Set where


[] : List A
_::_ : A → List A → List A

data _×_ (A B : Set) : Set where


_,_ : A → B → A × B

infixr 5 _::_
infixr 4 _,_
infixr 2 _×_

156 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Now suppose you would like to define an operator Prod that inputs a list of n sets and takes their cartesian product,
like this:

Prod (A :: B :: C :: []) = A × B × C

There is only one small problem with this definition. The type of Prod should be

Prod : List Set → Set

However, the definition of List A specified that A had to be a Set. Therefore, List Set is not a valid type. The
solution is to define a special version of the List operator that works for large sets:

data List1 (A : Set1 ) : Set1 where


[] : List1 A
_::_ : A → List1 A → List1 A

With this, we can indeed define:

Prod : List1 Set → Set


Prod [] = ⊤
Prod (A :: As) = A × Prod As

Universe polymorphism

To allow definitions of functions and datatypes that work for all possible universes Set𝑖 , Agda provides a type Level
of universe levels and level-polymorphic universes Set l where l : Level. For more information, see the page
on universe levels.

3.37.2 Agda’s sort system

The implementation of Agda’s sort system is closely based on the theory of pure type systems. The full sort system of
Agda consists of the following sorts:
• Set𝑖 and its universe-polymorphic variant Set l
• Prop𝑖 and its universe-polymorphic variant Prop l
• Set𝜔 𝑖

Sorts Set𝑖 and Set l

As explained in the introduction, Agda has a hierarchy of sorts Set𝑖 : Set𝑖+1 , where i is any concrete natural
number, i.e. 0, 1, 2, 3, . . . The sort Set is an abbreviation for Set0 .
You can also refer to these sorts with the alternative syntax Seti. That means that you can also write Set0, Set1,
Set2, etc., instead of Set0 , Set1 , Set2 .
In addition, Agda supports the universe-polymorphic version Set l where l : Level (see universe levels).

Sorts Prop𝑖 and Prop l

In addition to the hierarchy Set𝑖 , Agda also supports a second hierarchy Prop𝑖 : Set𝑖+1 (or Propi) of proof-
irrelevant propositions. Like Set, Prop also has a universe-polymorphic version Prop l where l : Level.

3.37. Sort System 157


Agda User Manual, Release 2.6.2

Sorts Set𝜔 𝑖

To assign a sort to types such as (l : Level) → Set l , Agda further supports an additional sort Set𝜔 that
stands above all sorts Set𝑖 .
Just as for Set and Prop, Set𝜔 is the lowest level at an infinite hierarchy Set𝜔 𝑖 : Set𝜔 𝑖+1 where Set𝜔 =
Set𝜔 0 . You can also refer to these sorts with the alternative syntax Set𝜔i. That means that you can also write
Set𝜔0, Set𝜔1, Set𝜔2, etc., instead of Set𝜔 0 , Set𝜔 1 , Set𝜔 2 .
Now it is allowed, for instance, to declare a datatype in Set𝜔. This means that Set𝜔 before the implementation of
this hierarchy, Set𝜔 used to be a term, and there was no bigger sort that it in Agda. Now a type can be assigned to it,
in this case, Set𝜔 1 .
However, unlike the standard hierarchy of universes Set𝑖 , this second hierarchy Set𝜔 𝑖 does not support universe
polymorphism. This means that it is not possible to quantify over all Set𝜔 𝑖 at once. For example, the expression ∀
{i} (A : Set𝜔 i) → A → A would not be a well-formed agda term. See the section on Set𝜔 on the page
on universe levels for more information.
Concerning other applications, It should not be necessary to refer to these sorts during normal usage of Agda, but they
might be useful for defining reflection-based macros.

Note: When --omega-in-omega is enabled, Set𝜔 𝑖 is considered to be equal to Set𝜔 for all i (thus rendering
Agda inconsistent).

3.37.3 Sort metavariables and unknown sorts

Under universe polymorphism, levels can be arbitrary terms, e.g., a level that contains free variables. Sometimes,
we will have to check that some expression has a valid type without knowing what sort it has. For this reason,
Agda’s internal representation of sorts implements a constructor (sort metavariable) representing an unknown sort. The
constraint solver can compute these sort metavariables, just like it does when computing regular term metavariables.
However, the presence of sort metavariables also means that sorts of other types can sometimes not be computed
directly. For this reason, Agda’s internal representation of sorts includes three additional constructors funSort,
univSort, and piSort. These constructors compute to the proper sort once enough metavariables in their argu-
ments have been solved.

Note: funSort, univSort and piSort are internal constructors that may be printed when evaluating a term.
The user can not enter them, nor introduce them in agda code. All these constructors do not represent new sorts but
instead, they compute to the right sort once their arguments are known.

funSort

The constructor funSort computes the sort of a function type even if the sort of the domain and the sort of the
codomain are still unknown.
To understand how funSort works in general, let us assume the following scenario:
• sA and sB are two (possibly different) sorts.
• A : sA, meaning that A is a type that has sort sA.
• B : sB, meaning that B is a (possibly different) type that has sort sB.

158 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Under these conditions, we can build the function type A → B : funSort sA sB. This type signature means
that the function type A → B has a (possibly unknown) but well-defined sort funSort sA sB, specified in terms
of the sorts of its domain and codomain.
If sA and sB happen to be known, then funSort sA sB can be computed to a sort value. We list below all the
possible computations that funSort can perform:

funSort Set𝜔 𝑖 Set𝜔 𝑗 = Set𝜔 𝑘 (where k = max(i,j))


funSort Set𝜔 𝑖 (Set b) = Set𝜔 𝑖
funSort Set𝜔 𝑖 (Prop b) = Set𝜔 𝑖
funSort (Set a) Set𝜔 𝑗 = Set𝜔 𝑗
funSort (Prop a) Set𝜔 𝑗 = Set𝜔 𝑗
funSort (Set a) (Set b) = Set (a ⊔ b)
funSort (Prop a) (Set b) = Set (a ⊔ b)
funSort (Set a) (Prop b) = Prop (a ⊔ b)
funSort (Prop a) (Prop b) = Prop (a ⊔ b)

Example: the sort of the function type ∀ {A} → A → A with normal form {A : _5} → A → A evaluates to
funSort (univSort _5) (funSort _5 _5) where:
• _5 is a metavariable that represents the sort of A.
• funSort _5 _5 is the sort of A → A.

Note: funSort can admit just two arguments, so it will be iterated when the function type has multiple argu-
ments. E.g. the function type ∀ {A} → A → A → A evaluates to funSort (univSort _5) (funSort
_5 (funSort _5 _5))

univSort

univSort returns the successor sort of a given sort.


Example: the sort of the function type ∀ {A} → A with normal form {A : _5} → A evaluates to funSort
(univSort _5) _5 where:
• univSort _5 is the sort where the sort of A lives, ie. the successor level of _5.
We list below all the possible computations that univSort can perform:

univSort (Set a) = Set (lsuc a)


univSort (Prop a) = Set (lsuc a)
univSort Set𝜔 𝑖 = Set𝜔 𝑖+1

piSort

Similarly, piSort s1 s2 is a constructor that computes the sort of a Π-type given the sort s1 of its domain and the
sort s2 of its codomain as arguments.
To understand how piSort works in general, we set the following scenario:
• sA and sB are two (possibly different) sorts.
• A : sA, meaning that A is a type that has sort sA.
• x : A, meaning that x has type A.
• B : sB, meaning that B is a type (possibly different than A) that has sort sB.

3.37. Sort System 159


Agda User Manual, Release 2.6.2

Under these conditions, we can build the dependent function type (x : A) → B : piSort sA (𝜆 x →
sB). This type signature means that the dependent function type (x : A) → B has a (possibly unknown) but
well-defined sort piSort sA sB, specified in terms of the element x : A and the sorts of its domain and
codomain.
We list below all the possible computations that piSort can perform:

piSort s1 (𝜆 x → s2) = funSort s1 s2 (if x does not occur freely in s2)


piSort (Set l ) (𝜆 x → s2) = Set𝜔 (if x occurs rigidly in s2)
piSort (Prop l ) (𝜆 x → s2) = Set𝜔 (if x occurs rigidly in s2)
piSort Set𝜔 𝑖 (𝜆 x → s2) = Set𝜔 𝑖 (if x occurs rigidly in s2)

With these rules, we can compute the sort of the function type ∀ {A} → ∀ {B} → B → A → B (or more
explicitly, {A : _9} {B : _7} → B → A → B) to be piSort (univSort _9) (𝜆 A → funSort
(univSort _7) (funSort _7 (funSort _9 _7)))
More examples:
• piSort Level (𝜆 l → Set l) evaluates to Set𝜔
• piSort (Set l) (𝜆 _ → Set l') evaluates to Set (l ⊔ l')
• univSort (Set l) evaluates to Set (lsuc l)
• piSort s (𝜆 x -> Set𝜔i) evaluates to funSort s Set𝜔

3.38 Syntactic Sugar

• Do-notation
– Desugaring
– Example
• Idiom brackets

3.38.1 Do-notation

A do-block consists of the layout keyword do followed by a sequence of do-statements, where

do-stmt ::= pat ← expr [where lam-clauses]


| let decls
| expr
lam-clause ::= pat → expr

The where clause of a bind is used to handle the cases not matched by the pattern left of the arrow. See details below.

Note: Arrows can use either unicode (←/→) or ASCII (<-/->) variants.

For example:

160 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

filter : {A : Set} → (A → Bool) → List A → List A


filter p xs = do
x ← xs
true ← p x :: []
where false → []
x :: []

Do-notation is desugared before scope checking and is translated into calls to _>>=_ and _>>_, whatever those
happen to be bound in the context of the do-block. This means that do-blocks are not tied to any particular notion of
monad. In fact if there are no monadic statements in the do block it can be used as sugar for a let:

pure-do : Nat → Nat


pure-do n = do
let p2 m = m * m
p4 m = p2 (p2 m)
p4 n

check-pure-do : pure-do 5 ≡ 625


check-pure-do = refl

Desugaring

Statement Sugar Desugars to


Simple bind
do x ← m m >>= 𝜆 x →
m' m'

Pattern bind
do p ← m m >>= 𝜆 where
where p𝑖 → m𝑖 p → m'
m' p𝑖 → m𝑖

Absurd match
do () ← m m >>= 𝜆 ()

Non-binding statement
do m m >>
m' m'

Let
do let ds let ds in
m' m'

If the pattern in the bind is exhaustive, the where-clause can be omitted.

Example

Do-notation becomes quite powerful together with pattern matching on indexed data. As an example, let us write a
correct-by-construction type checker for simply typed 𝜆-calculus.
First we define the raw terms, using de Bruijn indices for variables and explicit type annotations on the lambda:

3.38. Syntactic Sugar 161


Agda User Manual, Release 2.6.2

infixr 6 _=>_
data Type : Set where
nat : Type
_=>_ : (A B : Type) → Type

data Raw : Set where


var : (x : Nat) → Raw
lit : (n : Nat) → Raw
suc : Raw
app : (s t : Raw) → Raw
lam : (A : Type) (t : Raw) → Raw

Next up, well-typed terms:

Context = List Type

-- A proof of x ∈ xs is the index into xs where x is located.


infix 2 _∈_
data _∈_ {A : Set} (x : A) : List A → Set where
zero : ∀ {xs} → x ∈ x :: xs
suc : ∀ {y xs} → x ∈ xs → x ∈ y :: xs

data Term (Γ : Context) : Type → Set where


var : ∀ {A} (x : A ∈ Γ) → Term Γ A
lit : (n : Nat) → Term Γ nat
suc : Term Γ (nat => nat)
app : ∀ {A B} (s : Term Γ (A => B)) (t : Term Γ A) → Term Γ B
lam : ∀ A {B} (t : Term (A :: Γ) B) → Term Γ (A => B)

Given a well-typed term we can mechanically erase all the type information (except the annotation on the lambda) to
get the corresponding raw term:

rawIndex : ∀ {A} {x : A} {xs} → x ∈ xs → Nat


rawIndex zero = zero
rawIndex (suc i) = suc (rawIndex i)

eraseTypes : ∀ {Γ A} → Term Γ A → Raw


eraseTypes (var x) = var (rawIndex x)
eraseTypes (lit n) = lit n
eraseTypes suc = suc
eraseTypes (app s t) = app (eraseTypes s) (eraseTypes t)
eraseTypes (lam A t) = lam A (eraseTypes t)

Now we’re ready to write the type checker. The goal is to have a function that takes a raw term and either fails with a
type error, or returns a well-typed term that erases to the raw term it started with. First, lets define the return type. It’s
parameterised by a context and the raw term to be checked:

data WellTyped Γ e : Set where


ok : (A : Type) (t : Term Γ A) → eraseTypes t ≡ e → WellTyped Γ e

We’re going to need a corresponding type for variables:

data InScope Γ n : Set where


ok : (A : Type) (i : A ∈ Γ) → rawIndex i ≡ n → InScope Γ n

Lets also have a type synonym for the case when the erasure proof is refl:

162 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

infix 2 _ofType_
pattern _ofType_ x A = ok A x refl

Since this is a do-notation example we had better have a monad. Lets use the either monad with string errors:

TC : Set → Set
TC A = Either String A

typeError : ∀ {A} → String → TC A


typeError = left

For the monad operations, we are using instance arguments to infer which monad is being used.
We are going to need to compare types for equality. This is our first opportunity to take advantage of pattern matching
binds:

_=?=_ : (A B : Type) → TC (A ≡ B)
nat =?= nat = pure refl
nat =?= (_ => _) = typeError "type mismatch: nat ̸= _ => _"
(_ => _) =?= nat = typeError "type mismatch: _ => _ ̸= nat"
(A => B) =?= (A1 => B1 ) = do
refl ← A =?= A1
refl ← B =?= B1
pure refl

We will also need to look up variables in the context:

lookupVar : ∀ Γ n → TC (InScope Γ n)
lookupVar [] n = typeError "variable out of scope"
lookupVar (A :: Γ) zero = pure (zero ofType A)
lookupVar (A :: Γ) (suc n) = do
i ofType B ← lookupVar Γ n
pure (suc i ofType B)

Note how the proof obligation that the well-typed deBruijn index erases to the given raw index is taken care of
completely under the hood (in this case by the refl pattern in the ofType synonym).
Finally we are ready to implement the actual type checker:

infer : ∀ Γ e → TC (WellTyped Γ e)
infer Γ (var x) = do
i ofType A ← lookupVar Γ x
pure (var i ofType A)
infer Γ (lit n) = pure (lit n ofType nat)
infer Γ suc = pure (suc ofType nat => nat)
infer Γ (app e e1 ) = do
s ofType A => B ← infer Γ e
where _ ofType nat → typeError "numbers cannot be applied to arguments"
t ofType A1 ← infer Γ e1
refl ← A =?= A1
pure (app s t ofType B)
infer Γ (lam A e) = do
t ofType B ← infer (A :: Γ) e
pure (lam A t ofType A => B)

In the app case we use a where-clause to handle the error case when the function to be applied is well-typed, but does
not have a function type.

3.38. Syntactic Sugar 163


Agda User Manual, Release 2.6.2

3.38.2 Idiom brackets

Idiom brackets is a notation used to make it more convenient to work with applicative functors, i.e. functors F equipped
with two operations

pure : ∀ {A} → A → F A
_<*>_ : ∀ {A B} → F (A → B) → F A → F B

As do-notation, idiom brackets desugar before scope checking, so whatever the names pure and _<*>_ are bound
to gets used when desugaring the idiom brackets.
The syntax for idiom brackets is

(| e a1 .. a𝑛 |)

or using unicode lens brackets L (U+2987) and M (U+2988):

L e a1 .. a𝑛 M

This expands to (assuming left associative _<*>_)

pure e <*> a1 <*> .. <*> a𝑛

Idiom brackets work well with operators, for instance

(| if a then b else c |)

desugars to

pure if_then_else_ <*> a <*> b <*> c

Idiom brackets also support none or multiple applications. If the applicative functor has an additional binary operation

_<|>_ : ∀ {A B} → F A → F A → F A

then idiom brackets support multiple applications separated by a vertical bar |, i.e.

(| e1 a1 .. a𝑛 | e2 a1 .. a𝑚 | .. | e𝑘 a1 .. a𝑙 |)

which expands to (assuming right associative _<|>_)

(pure e1 <*> a1 <*> .. <*> a𝑛 ) <|> ((pure e2 <*> a1 <*> .. <*> a𝑚 ) <|> (pure e𝑘 <*> a1
˓→<*> .. <*> a𝑙 ))

Idiom brackets without any application (|) or LM expend to empty if

empty : ∀ {A} → F A

is in scope. An applicative functor with empty and _<|>_ is typically called Alternative.
Note that pure, _<*>_, and _<|>_ need not be in scope to use (|).
Limitations:
• Binding syntax and operator sections cannot appear immediately inside idiom brackets.
• The top-level application inside idiom brackets cannot include implicit applications, so

164 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

(| foo {x = e} a b |)

is illegal. In case the e is pure you can write

(| (foo {x = e}) a b |)

which desugars to

pure (foo {x = e}) <*> a <*> b

3.39 Syntax Declarations

Note: This is a stub

It is now possible to declare user-defined syntax that binds identifiers. Example:

record Σ (A : Set) (B : A → Set) : Set where


constructor _,_
field fst : A
snd : B fst

syntax Σ A (𝜆 x → B) = [ x ∈ A ] × B

witness : ∀ {A B} → [ x ∈ A ] × B → A
witness (x , _) = x

The syntax declaration for Σ implies that x is in scope in B, but not in A.


You can give fixity declarations along with syntax declarations:

infix 5 Σ
syntax Σ A (𝜆 x → B) = [ x ∈ A ] × B

The fixity applies to the syntax, not the name; syntax declarations are also restricted to ordinary, non-operator names.
The following declaration is disallowed:

syntax _==_ x y = x === y

Syntax declarations must also be linear; the following declaration is disallowed:

syntax wrong x = x + x

Syntax declarations can have implicit arguments. For example:

id : ∀ {a}{A : Set a} -> A -> A


id x = x

syntax id {A} x = x ∈ A

Unlike mixfix operators that can be used unapplied using the name including all the underscores, or partially applied
by replacing only some of the underscores by arguments, syntax must be fully applied.

3.39. Syntax Declarations 165


Agda User Manual, Release 2.6.2

3.40 Telescopes

Note: This is a stub.

3.40.1 Irrefutable Patterns in Binding Positions

Since Agda 2.6.1, irrefutable patterns can be used at every binding site in a telescope to take the bound value of record
type apart. The type of the second projection out of a dependent pair will for instance naturally mention the value of
the first projection. Its type can be defined directly using an irrefutable pattern as follows:
proj2 : ((a , _) : Σ A B) → B a

And this second projection can be implemented with a lamba-abstraction using one of these irrefutable patterns taking
the pair apart:
proj2 = 𝜆 (_ , b) → b

Using an as-pattern makes it possible to name the argument and to take it apart at the same time. We can for instance
prove that any pair is equal to the pairing of its first and second projections, a property commonly called eta-equality:
eta : (p@(a , b) : Σ A B) → p ≡ (a , b)
eta p = refl

3.41 Termination Checking

Not all recursive functions are permitted - Agda accepts only these recursive schemas that it can mechanically prove
terminating.

3.41.1 Primitive recursion

In the simplest case, a given argument must be exactly one constructor smaller in each recursive call. We call this
scheme primitive recursion. A few correct examples:
plus : Nat → Nat → Nat
plus zero m = m
plus (suc n) m = suc (plus n m)

natEq : Nat → Nat → Bool


natEq zero zero = true
natEq zero (suc m) = false
natEq (suc n) zero = false
natEq (suc n) (suc m) = natEq n m

Both plus and natEq are defined by primitive recursion.


The recursive call in plus is OK because n is a subexpression of suc n (so n is structurally smaller than suc n).
So every time plus is recursively called the first argument is getting smaller and smaller. Since a natural number can
only have a finite number of suc constructors we know that plus will always terminate.
natEq terminates for the same reason, but in this case we can say that both the first and second arguments of natEq
are decreasing.

166 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

3.41.2 Structural recursion

Agda’s termination checker allows more definitions than just primitive recursive ones – it allows structural recursion.
This means that we require recursive calls to be on a (strict) subexpression of the argument (see fib below) - this is
more general that just taking away one constructor at a time.

fib : Nat → Nat


fib zero = zero
fib (suc zero) = suc zero
fib (suc (suc n)) = plus (fib n) (fib (suc n))

It also means that arguments may decrease in an lexicographic order - this can be thought of as nested primitive
recursion (see ack below).

ack : Nat → Nat → Nat


ack zero m = suc m
ack (suc n) zero = ack n (suc zero)
ack (suc n) (suc m) = ack n (ack (suc n) m)

In ack either the first argument decreases or it stays the same and the second one decreases. This is the same as a
lexicographic ordering.

3.41.3 With-functions

3.41.4 Pragmas and Options

• The NON_TERMINATING pragma


This is a safer version of TERMINATING which doesn’t treat the affected functions as terminating. This means
that NON_TERMINATING functions do not reduce during type checking. They do reduce at run-time and when
invoking C-c C-n at top-level (but not in a hole). The pragma was added in Agda 2.4.2.
• The TERMINATING pragma
Switches off termination checker for individual function definitions and mutual blocks and marks them as ter-
minating. Since Agda 2.4.2.1 replaced the NO_TERMINATION_CHECK pragma.
The pragma must precede a function definition or a mutual block. The pragma cannot be used in --safe mode.
Examples:
– Skipping a single definition: before type signature:

{-# TERMINATING #-}


a : A
a = a

– Skipping a single definition: before first clause:

b : A
{-# TERMINATING #-}
b = b

– Skipping an old-style mutual block: Before mutual keyword:

3.41. Termination Checking 167


Agda User Manual, Release 2.6.2

{-# TERMINATING #-}


mutual
c : A
c = d

d : A
d = c

– Skipping an old-style mutual block: Somewhere within mutual block before a type signature or first func-
tion clause:

mutual
{-# TERMINATING #-}
e : A
e = f

f : A
f = e

– Skipping a new-style mutual block: Anywhere before a type signature or first function clause in the block:

g : A
h : A

g = h
{-# TERMINATING #-}
h = g

3.41.5 References

Andreas Abel, Foetus – termination checker for simple functional programs

3.42 Universe Levels

Agda’ type system includes an infinite hierarchy of universes Set𝑖 : Set𝑖+1 . This hierarchy enables quantifica-
tion over arbitrary types without running into the inconsistency that follows from Set : Set. These universes are
further detailed on the page on Agda’s sort system.
However, when working with this hierarchy it can quickly get tiresome to repeat the same definition at different
universe levels. For example, we might be forced to define new datatypes data List (A : Set) : Set,
data List1 (A : Set1 ) : Set1 , etc. Also every function on lists (such as append) must be re-defined,
and every theorem about such functions must be re-proved, for every possible level.
The solution to this problem is universe polymorphism. Agda provides a special primitive type Level, whose ele-
ments are possible levels of universes. In fact, the notation for the n th universe, Set𝑛 , is just an abbreviation for Set
n, where n : Level is a level. We can use this to write a polymorphic List operator that works at any level. The
library Agda.Primitive must be imported to access the Level type. The definition then looks like this:

open import Agda.Primitive

data List {n : Level} (A : Set n) : Set n where


[] : List A
_::_ : A → List A → List A

168 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

This new operator works at all levels; for example, we have

List Nat : Set


List Set : Set1
List Set1 : Set2

3.42.1 Level arithmetic

Even though we don’t have the number of levels specified, we know that there is a lowest level lzero, and for each
level n, there exists some higher level lsuc n; therefore, the set of levels is infinite. In addition, we can also take the
least upper bound n ⊔ m of two levels. In summary, the following (and only the following) operations on levels are
provided:

lzero : Level
lsuc : (n : Level) → Level
_⊔_ : (n m : Level) → Level

This is sufficient for most purposes; for example, we can define the cartesian product of two types of arbitrary (and
not necessarily equal) levels like this:

data _×_ {n m : Level} (A : Set n) (B : Set m) : Set (n ⊔ m) where


_,_ : A → B → A × B

With this definition, we have, for example:

Nat × Nat : Set


Nat x Set : Set1
Set × Set : Set1

3.42.2 Intrinsic level properties

Levels and their associated operations have some properties which are internally and automatically solved by the
compiler. This means that we can replace some expressions with others, without worrying about the expressions for
their corresponding levels matching exactly.
For example, we can write:

_ : {F : (l : Level) → Set l} {l1 l2 : Level} → F (l1 ⊔ l2) → F (l2 ⊔ l1)


_ = 𝜆 x → x

and Agda does the conversion from F (l1 ⊔ l2) to F (l2 ⊔ l1) automatically.
Here is a list of the level properties:
• Idempotence: a ⊔ a is the same as a.
• Associativity: (a ⊔ b) ⊔ c is the same as a ⊔ (b ⊔ c).
• Commutativity: a ⊔ b is the same as b ⊔ a.
• Distributivity of lsuc over ⊔: lsuc (a ⊔ b) is the same as lsuc a ⊔ lsuc b.
• Neutrality of lzero: a ⊔ lzero is the same as a.
• Subsumption: a ⊔ lsuc a is the same as lsuc a. Notably, this also holds for arbitrarily many lsuc
usages: a ⊔ lsuc (lsuc a) is also the same as lsuc (lsuc a).

3.42. Universe Levels 169


Agda User Manual, Release 2.6.2

3.42.3 forall notation

From the fact that we write Set n, it can always be inferred that n is a level. Therefore, when defining universe-
polymorphic functions, it is common to use the ∀ (or forall) notation. For example, the type of the universe-
polymorphic map operator on lists can be written

map : ∀ {n m} {A : Set n} {B : Set m} → (A → B) → List A → List B

which is equivalent to

map : {n m : Level} {A : Set n} {B : Set m} → (A → B) → List A → List B

3.42.4 Expressions of sort Set𝜔

In a sense, universes were introduced to ensure that every Agda expression has a type, including expressions such
as Set, Set1 , etc. However, the introduction of universe polymorphism inevitably breaks this property again, by
creating some new terms that have no type. Consider the polymorphic singleton set Unit n : Set𝑛 , defined by

data Unit (n : Level) : Set n where


<> : Unit n

It is well-typed, and has type

Unit : (n : Level) → Set n

However, the type (n : Level) → Set n, which is a valid Agda expression, does not belong to any universe
in the Set hierarchy. Indeed, the expression denotes a function mapping levels to sorts, so if it had a type, it should be
something like Level → Sort, where Sort is the collection of all sorts. But if Agda were to support a sort Sort
of all sorts, it would be a sort itself, so in particular we would have Sort : Sort. Just like Type : Type, this
would leads to circularity and inconsistency.
Instead, Agda introduces a new sort Set𝜔 that stands above all sorts Set l , but is not itself part of the hierarchy. For
example, Agda assigns the expression (n : Level) → Set n to be of type Set𝜔.
Set𝜔 is itself the first step in another infinite hierarchy Set𝜔 𝑖 : Set𝜔 𝑖+1 . However, this hierarchy does not
support universe polymorphism, i.e. there are no sorts Set𝜔 l for l : Level. Allowing this would require a new
universe Set2𝜔, which would then naturally lead to Set2𝜔 1 , and so on. Disallowing universe polymorphism for
Set𝜔 𝑖 avoids the need for such even larger sorts. This is an intentional design decision.

3.42.5 Pragmas and options

• The option --type-in-type disables the checking of universe level consistency for the whole file.
• The option --omega-in-omega enables the typing rule Set𝜔 : Set𝜔 (thus making Agda inconsistent)
but otherwise leaves universe checks intact.
• The pragma {-# NO_UNIVERSE_CHECK #-} can be put in front of a data or record type to disable universe
consistency checking locally. Example:

{-# NO_UNIVERSE_CHECK #-}


data U : Set where
el : Set → U

This pragma applies only to the check that the universe level of the type of each constructor argument is less
than or equal to the universe level of the datatype, not to any other checks.

170 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

New in version 2.6.0.


The options --type-in-type and --omega-in-omega and the pragma {-# NO_UNIVERSE_CHECK #-}
cannot be used with –safe.

3.43 With-Abstraction

• Usage
– Generalisation
– Nested with-abstractions
– Simultaneous abstraction
– Making with-abstractions hidden and/or irrelevant
– Using underscores and variables in pattern repetition
– Irrefutable With
– Rewrite
– With-abstraction equality
– Alternatives to with-abstraction
– Termination checking
– Performance considerations
• Technical details
– Examples
– Ill-typed with-abstractions

With-abstraction was first introduced by Conor McBride [McBride2004] and lets you pattern match on the result of
an intermediate computation by effectively adding an extra argument to the left-hand side of your function.

3.43.1 Usage

In the simplest case the with construct can be used just to discriminate on the result of an intermediate computation.
For instance
filter : {A : Set} → (A → Bool) → List A → List A
filter p [] = []
filter p (x :: xs) with p x
filter p (x :: xs) | true = x :: filter p xs
filter p (x :: xs) | false = filter p xs

The clause containing the with-abstraction has no right-hand side. Instead it is followed by a number of clauses with
an extra argument on the left, separated from the original arguments by a vertical bar (|).
When the original arguments are the same in the new clauses you can use the ... syntax:
filter : {A : Set} → (A → Bool) → List A → List A
filter p [] = []
(continues on next page)

3.43. With-Abstraction 171


Agda User Manual, Release 2.6.2

(continued from previous page)


filter p (x :: xs) with p x
... | true = x :: filter p xs
... | false = filter p xs

In this case ... expands to filter p (x :: xs). There are three cases where you have to spell out the left-hand
side:
• If you want to do further pattern matching on the original arguments.
• When the pattern matching on the intermediate result refines some of the other arguments (see Dot patterns).
• To disambiguate the clauses of nested with-abstractions (see Nested with-abstractions below).

Generalisation

The power of with-abstraction comes from the fact that the goal type and the type of the original arguments are
generalised over the value of the scrutinee. See Technical details below for the details. This generalisation is important
when you have to prove properties about functions defined using with. For instance, suppose we want to prove that
the filter function above satisfies some property P. Starting out by pattern matching of the list we get the following
(with the goal types shown in the holes)
postulate P : ∀ {A} → List A → Set
postulate p-nil : ∀ {A} → P {A} []
postulate Q : Set
postulate q-nil : Q

proof : {A : Set} (p : A → Bool) (xs : List A) → P (filter p xs)


proof p [] = {! P [] !}
proof p (x :: xs) = {! P (filter p (x :: xs) | p x) !}

In the cons case we have to prove that P holds for filter p (x :: xs) | p x. This is the syntax for a stuck
with-abstraction—filter cannot reduce since we don’t know the value of p x. This syntax is used for printing, but
is not accepted as valid Agda code. Now if we with-abstract over p x, but don’t pattern match on the result we get:
proof : {A : Set} (p : A → Bool) (xs : List A) → P (filter p xs)
proof p [] = p-nil
proof p (x :: xs) with p x
... | r = {! P (filter p (x :: xs) | r) !}

Here the p x in the goal type has been replaced by the variable r introduced for the result of p x. If we pattern match
on r the with-clauses can reduce, giving us:
proof : {A : Set} (p : A → Bool) (xs : List A) → P (filter p xs)
proof p [] = p-nil
proof p (x :: xs) with p x
... | true = {! P (x :: filter p xs) !}
... | false = {! P (filter p xs) !}

Both the goal type and the types of the other arguments are generalised, so it works just as well if we have an argument
whose type contains filter p xs.
proof2 : {A : Set} (p : A → Bool) (xs : List A) → P (filter p xs) → Q
proof2 p [] _ = q-nil
proof2 p (x :: xs) H with p x
... | true = {! H : P (x :: filter p xs) !}
... | false = {! H : P (filter p xs) !}

172 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

The generalisation is not limited to scrutinees in other with-abstractions. All occurrences of the term in the goal type
and argument types will be generalised.
Note that this generalisation is not always type correct and may result in a (sometimes cryptic) type error. See Ill-typed
with-abstractions below for more details.

Nested with-abstractions

With-abstractions can be nested arbitrarily. The only thing to keep in mind in this case is that the ... syntax applies
to the closest with-abstraction. For example, suppose you want to use ... in the definition below.

compare : Nat → Nat → Comparison


compare x y with x < y
compare x y | false with y < x
compare x y | false | false = equal
compare x y | false | true = greater
compare x y | true = less

You might be tempted to replace compare x y with ... in all the with-clauses as follows.

compare : Nat → Nat → Comparison


compare x y with x < y
... | false with y < x
... | false = equal
... | true = greater
... | true = less -- WRONG

This, however, would be wrong. In the last clause the ... is interpreted as belonging to the inner with-abstraction
(the whitespace is not taken into account) and thus expands to compare x y | false | true. In this case you
have to spell out the left-hand side and write

compare : Nat → Nat → Comparison


compare x y with x < y
... | false with y < x
... | false = equal
... | true = greater
compare x y | true = less

Simultaneous abstraction

You can abstract over multiple terms in a single with-abstraction. To do this you separate the terms with vertical bars
(|).

compare : Nat → Nat → Comparison


compare x y with x < y | y < x
... | true | _ = less
... | _ | true = greater
... | false | false = equal

In this example the order of abstracted terms does not matter, but in general it does. Specifically, the types of later
terms are generalised over the values of earlier terms. For instance

postulate plus-commute : (a b : Nat) → a + b ≡ b + a


postulate P : Nat → Set

3.43. With-Abstraction 173


Agda User Manual, Release 2.6.2

thm : (a b : Nat) → P (a + b) → P (b + a)
thm a b t with a + b | plus-commute a b
thm a b t | ab | eq = {! t : P ab, eq : ab ≡ b + a !}

Note that both the type of t and the type of the result eq of plus-commute a b have been generalised over a +
b. If the terms in the with-abstraction were flipped around, this would not be the case. If we now pattern match on eq
we get
thm : (a b : Nat) → P (a + b) → P (b + a)
thm a b t with a + b | plus-commute a b
thm a b t | .(b + a) | refl = {! t : P (b + a) !}

and can thus fill the hole with t. In effect we used the commutativity proof to rewrite a + b to b + a in the
type of t. This is such a useful thing to do that there is special syntax for it. See Rewrite below. A limitation of
generalisation is that only occurrences of the term that are visible at the time of the abstraction are generalised over,
but more instances of the term may appear once you start filling in the right-hand side or do further matching on the
left. For instance, consider the following contrived example where we need to match on the value of f n for the type
of q to reduce, but we then want to apply q to a lemma that talks about f n:
postulate
R : Set
P : Nat → Set
f : Nat → Nat
lemma : ∀ n → P (f n) → R

Q : Nat → Set
Q zero = ⊥
Q (suc n) = P (suc n)

proof : (n : Nat) → Q (f n) → R
proof n q with f n
proof n () | zero
proof n q | suc fn = {! q : P (suc fn) !}

Once we have generalised over f n we can no longer apply the lemma, which needs an argument of type P (f n).
To solve this problem we can add the lemma to the with-abstraction:
proof : (n : Nat) → Q (f n) → R
proof n q with f n | lemma n
proof n () | zero | _
proof n q | suc fn | lem = lem q

In this case the type of lemma n (P (f n) → R) is generalised over f n so in the right-hand side of the last
clause we have q : P (suc fn) and lem : P (suc fn) → R.
See With-abstraction equality below for an alternative approach.

Making with-abstractions hidden and/or irrelevant

It is possible to add hiding and relevance annotations to with expressions. For example:
module _ (A B : Set) (recompute : .B → .{{A}} → B) where

_$_ : .(A → B) → .A → B
f $ x with .{f} | .(f x) | .{{x}}
... | y = recompute y

174 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

This can be useful for hiding with-abstractions that you do not need to match on but that need to be abstracted over
for the result to be well-typed. It can also be used to abstract over the fields of a record type with irrelevant fields, for
example:
record EqualBools : Set1 where
field
bool1 : Bool
bool2 : Bool
.same : bool1 ≡ bool2
open EqualBools

example : EqualBools → EqualBools


example x with bool1 x | bool2 x | .(same x)
... | true | y´ | eq´ = record { bool1 = true; bool2 = y´; same = eq´ }
... | false | y´ | eq´ = record { bool1 = false; bool2 = y´; same = eq´ }

Using underscores and variables in pattern repetition

If an ellipsis . . . cannot be used, the with-clause has to repeat (or refine) the patterns of the parent clause. Since Agda
2.5.3, such patterns can be replaced by underscores _ if the variables they bind are not needed. Here is a (slightly
contrived) example:
record R : Set where
coinductive -- disallows matching
field f : Bool
n : Nat

data P (r : R) : Nat → Set where


fTrue : R.f r ≡ true → P r zero
nSuc : P r (suc (R.n r))

data Q : (b : Bool) (n : Nat) → Set where


true! : Q true zero
suc! : ∀{b n} → Q b (suc n)

test : (r : R) {n : Nat} (p : P r n) → Q (R.f r) n


test r nSuc = suc!
test r (fTrue p) with R.f r
test _ (fTrue ()) | false
test _ _ | true = true! -- underscore instead of (isTrue _)

Since Agda 2.5.4, patterns can also be replaced by a variable:


f : List Nat → List Nat
f [] = []
f (x :: xs) with f xs
f xs0 | r = ?

The variable xs0 is treated as a let-bound variable with value .x :: .xs (where .x : Nat and .xs : List Nat are out of
scope). Since with-abstraction may change the type of variables, the instantiation of such let-bound variables are type
checked again after with-abstraction.

Irrefutable With

When a pattern is irrefutable, we can use a pattern-matching with instead of a traditional with block. This gives us
a lightweight syntax to make a lot of observations before using a “proper” with block. For a basic example of such

3.43. With-Abstraction 175


Agda User Manual, Release 2.6.2

an irrefutable pattern, see this unfolding lemma for pred

pred : Nat → Nat


pred zero = zero
pred (suc n) = n

NotNull : Nat → Set


NotNull zero = ⊥ -- false
NotNull (suc n) = ⊤ -- trivially true

pred-correct : ∀ n (pr : NotNull n) → suc (pred n) ≡ n


pred-correct n pr with suc p ← n = refl

In the above code snippet we do not need to entertain the idea that n could be equal to zero: Agda detects that the
proof pr allows us to dismiss such a case entirely.
The patterns used in such an inversion clause can be arbitrary. We can for instance have deep patterns, e.g. projecting
out the second element of a vector whose length is neither 0 nor 1:

infixr 5 _::_
data Vec {a} (A : Set a) : Nat → Set a where
[] : Vec A zero
_::_ : ∀ {n} → A → Vec A n → Vec A (suc n)

second : ∀ {n} {pr : NotNull (pred n)} → Vec A n → A


second vs with (_ :: v :: _) ← vs = v

Remember the example of simultaneous abstraction from above. A simultaneous rewrite / pattern-matching with is
to be understood as being nested. That is to say that the type refinements introduced by the first case analysis may be
necessary to type the following ones.
In the following example, in focusAt we are only able to perform the splitAt we are interested in because we
have massaged the type of the vector argument using suc-+ first.

suc-+ : ∀ m n → suc m + n ≡ m + suc n


suc-+ zero n = refl
suc-+ (suc m) n rewrite suc-+ m n = refl

infixr 1 _×_
_×_ : ∀ {a b} (A : Set a) (B : Set b) → Set ?
A × B = Σ A (𝜆 _ → B)

splitAt : ∀ m {n} → Vec A (m + n) → Vec A m × Vec A n


splitAt zero xs = ([] , xs)
splitAt (suc m) (x :: xs) with (ys , zs) ← splitAt m xs = (x :: ys , zs)

-- focusAt m (x0 :: · · · :: x𝑚−1 :: x𝑚 :: x𝑚+1 :: · · · :: x𝑚+𝑛 )


-- returns ((x0 :: · · · :: x𝑚−1 ) , x𝑚 , (x𝑚+1 :: · · · :: x𝑚+𝑛 ))
focusAt : ∀ m {n} → Vec A (suc (m + n)) → Vec A m × A × Vec A n
focusAt m {n} vs rewrite suc-+ m n
with (before , focus :: after) ← splitAt m vs
= (before , focus , after)

You can alternate arbitrarily many rewrite and pattern-matching with clauses and still perform a with abstraction
afterwards if necessary.

176 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

Rewrite

Remember example of simultaneous abstraction from above.

postulate plus-commute : (a b : Nat) → a + b ≡ b + a

thm : (a b : Nat) → P (a + b) → P (b + a)
thm a b t with a + b | plus-commute a b
thm a b t | .(b + a) | refl = t

This pattern of rewriting by an equation by with-abstracting over it and its left-hand side is common enough that there
is special syntax for it:

thm : (a b : Nat) → P (a + b) → P (b + a)
thm a b t rewrite plus-commute a b = t

The rewrite construction takes a term eq of type lhs ≡ rhs, where _≡_ is the built-in equality type, and
expands to a with-abstraction of lhs and eq followed by a match of the result of eq against refl:

f ps rewrite eq = v

-->

f ps with lhs | eq
... | .rhs | refl = v

One limitation of the rewrite construction is that you cannot do further pattern matching on the arguments after
the rewrite, since everything happens in a single clause. You can however do with-abstractions after the rewrite. For
instance,

postulate T : Nat → Set

isEven : Nat → Bool


isEven zero = true
isEven (suc zero) = false
isEven (suc (suc n)) = isEven n

thm1 : (a b : Nat) → T (a + b) → T (b + a)
thm1 a b t rewrite plus-commute a b with isEven a
thm1 a b t | true = t
thm1 a b t | false = t

Note that the with-abstracted arguments introduced by the rewrite (lhs and eq) are not visible in the code.

With-abstraction equality

When you with-abstract a term t you lose the connection between t and the new argument representing its value.
That’s fine as long as all instances of t that you care about get generalised by the abstraction, but as we saw above
this is not always the case. In that example we used simultaneous abstraction to make sure that we did capture all the
instances we needed.
An alternative to that is to get Agda to remember in an equality proof that the patterns in the with clauses come from
the expression you abstracted over. This is possible using the in keyword.
In the following artificial example, we try to prove that there exists two numbers such that one equals the double of
the other. We start by computing the double of our input m and call it n. We can then return the nested pair containing

3.43. With-Abstraction 177


Agda User Manual, Release 2.6.2

m, n, and we now need a proof that m + m ≡ n. Luckily we used in eq when computing n as m + m and this eq
is exactly the proof we need.
double : Nat → Σ Nat (𝜆 m → Σ Nat (𝜆 n → m + m ≡ n))
double m with n ← m + m in eq = m , n , eq

For a more natural example, we prove that filter (defined at the top of this page) is idempotent. That is to say that
applying it twice to an input list is the same as only applying it once.
In the filter-filter p (x :: xs) case, abstracting over and then matching on the result of p x allows the
first call to filter p (x :: xs) to reduce.
In case the element x is kept (i.e. p x is true), the second call to filter on the LHS goes on to performs the same
p x test. Because we have retained the proof that p x ≡ true in eq, we are able to rewrite by this equality and
get it to reduce too.
This leads to just enough computation that we can finish the proof with an appeal to congruence and the induction
hypothesis.
filter-filter : ∀ {A} p (xs : List A) → filter p (filter p xs) ≡ filter p xs
filter-filter p [] = refl
filter-filter p (x :: xs) with p x in eq
... | false = filter-filter p xs -- easy
... | true -- second filter stuck on `p x`: rewrite by `eq`!
rewrite eq = cong (x ::_) (filter-filter p xs)

Alternatives to with-abstraction

Although with-abstraction is very powerful there are cases where you cannot or don’t want to use it. For instance,
you cannot use with-abstraction if you are inside an expression in a right-hand side. In that case there are a couple of
alternatives.

Pattern lambdas

Agda does not have a primitive case construct, but one can be emulated using pattern matching lambdas. First you
define a function case_of_ as follows:
case_of_ : ∀ {a b} {A : Set a} {B : Set b} → A → (A → B) → B
case x of f = f x

You can then use this function with a pattern matching lambda as the second argument to get a Haskell-style case
expression:
filter : {A : Set} → (A → Bool) → List A → List A
filter p [] = []
filter p (x :: xs) =
case p x of
𝜆 { true → x :: filter p xs
; false → filter p xs
}

This version of case_of_ only works for non-dependent functions. For dependent functions the target type will in
most cases not be inferrable, but you can use a variant with an explicit B for this case:
case_return_of_ : ∀ {a b} {A : Set a} (x : A) (B : A → Set b) → (∀ x → B x) → B x
case x return B of f = f x

178 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

The dependent version will let you generalise over the scrutinee, just like a with-abstraction, but you have to do it
manually. Two things that it will not let you do is
• further pattern matching on arguments on the left-hand side, and
• refine arguments on the left by the patterns in the case expression. For instance if you matched on a Vec A n
the n would be refined by the nil and cons patterns.

Helper functions

Internally with-abstractions are translated to auxiliary functions (see Technical details below) and you can always
write these functions manually. The downside is that the type signature for the helper function needs to be written out
explicitly, but fortunately the Emacs Mode has a command (C-c C-h) to generate it using the same algorithm that
generates the type of a with-function.

Termination checking

The termination checker runs on the translated auxiliary functions, which means that some code that looks like it
should pass termination checking does not. Specifically this happens in call chains like c1 (c2 x) −→ c1 x
where the recursive call is under a with-abstraction. The reason is that the auxiliary function only gets passed x, so the
call chain is actually c1 (c2 x) −→ x −→ c1 x, and the termination checker cannot see that this is terminating.
For example:

data D : Set where


[_] : Nat → D

fails : D → Nat
fails [ zero ] = zero
fails [ suc n ] with some-stuff
... | _ = fails [ n ]

The easiest way to work around this problem is to perform a with-abstraction on the recursive call up front:

fixed : D → Nat
fixed [ zero ] = zero
fixed [ suc n ] with fixed [ n ] | some-stuff
... | rec | _ = rec

If the function takes more arguments you might need to abstract over a partial application to just the structurally
recursive argument. For instance,

fails : Nat → D → Nat


fails _ [ zero ] = zero
fails _ [ suc n ] with some-stuff
... | m = fails m [ n ]

fixed : Nat → D → Nat


fixed _ [ zero ] = zero
fixed _ [ suc n ] with (𝜆 m → fixed m [ n ]) | some-stuff
... | rec | m = rec m

A possible complication is that later with-abstractions might change the type of the abstracted recursive call:

3.43. With-Abstraction 179


Agda User Manual, Release 2.6.2

T : D → Set
suc-T : ∀ {n} → T [ n ] → T [ suc n ]
zero-T : T [ zero ]

fails : (d : D) → T d
fails [ zero ] = zero-T
fails [ suc n ] with some-stuff
... | _ with [ n ]
... | z = suc-T (fails [ n ])

Trying to abstract over the recursive call as before does not work in this case.

still-fails : (d : D) → T d
still-fails [ zero ] = zero-T
still-fails [ suc n ] with still-fails [ n ] | some-stuff
... | rec | _ with [ n ]
... | z = suc-T rec -- Type error because rec : T z

To solve the problem you can add rec to the with-abstraction messing up its type. This will prevent it from having its
type changed:

fixed : (d : D) → T d
fixed [ zero ] = zero-T
fixed [ suc n ] with fixed [ n ] | some-stuff
... | rec | _ with rec | [ n ]
... | _ | z = suc-T rec

Performance considerations

The generalisation step of a with-abstraction needs to normalise the scrutinee and the goal and argument types to make
sure that all instances of the scrutinee are generalised. The generalisation also needs to be type checked to make sure
that it’s not ill-typed. This makes it expensive to type check a with-abstraction if
• the normalisation is expensive,
• the normalised form of the goal and argument types are big, making finding the instances of the scrutinee
expensive,
• type checking the generalisation is expensive, because the types are big, or because checking them involves
heavy computation.
In these cases it is worth looking at the alternatives to with-abstraction from above.

3.43.2 Technical details

Internally with-abstractions are translated to auxiliary functions—there are no with-abstractions in the Core language.
This translation proceeds as follows. Given a with-abstraction

𝑓 :Γ→𝐵
𝑓 𝑝𝑠 with 𝑡1 | . . . | 𝑡𝑚
𝑓 𝑝𝑠1 | 𝑞11 | . . . | 𝑞1𝑚 = 𝑣1
..
.
𝑓 𝑝𝑠𝑛 | 𝑞𝑛1 | . . . | 𝑞𝑛𝑚 = 𝑣𝑛

where ∆ ⊢ 𝑝𝑠 : Γ (i.e. ∆ types the variables bound in 𝑝𝑠), we

180 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

• Infer the types of the scrutinees 𝑡1 : 𝐴1 , . . . , 𝑡𝑚 : 𝐴𝑚 .


• Partition the context ∆ into ∆1 and ∆2 such that ∆1 is the smallest context where ∆1 ⊢ 𝑡𝑖 : 𝐴𝑖 for all 𝑖, i.e.,
where the scrutinees are well-typed. Note that the partitioning is not required to be a split, ∆1 ∆2 can be a
(well-formed) reordering of ∆.
• Generalise over the 𝑡𝑖 s, by computing

𝐶 = (𝑤1 : 𝐴1 )(𝑤1 : 𝐴′2 ) . . . (𝑤𝑚 : 𝐴′𝑚 ) → ∆′2 → 𝐵 ′

such that the normal form of 𝐶 does not contain any 𝑡𝑖 and

𝐴′𝑖 [𝑤1 := 𝑡1 . . . 𝑤𝑖−1 := 𝑡𝑖−1 ] ≃ 𝐴𝑖


(∆′2 → 𝐵 ′ )[𝑤1 := 𝑡1 . . . 𝑤𝑚 := 𝑡𝑚 ] ≃ ∆2 → 𝐵

where 𝑋 ≃ 𝑌 is equality of the normal forms of 𝑋 and 𝑌 . The type of the auxiliary function is then ∆1 → 𝐶.
• Check that ∆1 → 𝐶 is type correct, which is not guaranteed (see below).
• Add a function 𝑓𝑎𝑢𝑥 , mutually recursive with 𝑓 , with the definition

𝑓𝑎𝑢𝑥 : ∆1 → 𝐶
𝑓𝑎𝑢𝑥 𝑝𝑠11 qs 1 𝑝𝑠21 = 𝑣1
..
.
𝑓𝑎𝑢𝑥 𝑝𝑠1𝑛 qs 𝑛 𝑝𝑠2𝑛 = 𝑣𝑛

where qs 𝑖 = 𝑞𝑖1 . . . 𝑞𝑖𝑚 , and 𝑝𝑠1𝑖 : ∆1 and 𝑝𝑠2𝑖 : ∆2 are the patterns from 𝑝𝑠𝑖 corresponding to the variables of
𝑝𝑠. Note that due to the possible reordering of the partitioning of ∆ into ∆1 and ∆2 , the patterns 𝑝𝑠1𝑖 and 𝑝𝑠2𝑖
can be in a different order from how they appear 𝑝𝑠𝑖 .
• Replace the with-abstraction by a call to 𝑓𝑎𝑢𝑥 resulting in the final definition

𝑓 :Γ→𝐵
𝑓 𝑝𝑠 = 𝑓𝑎𝑢𝑥 xs 1 𝑡𝑠 xs 2

where 𝑡𝑠 = 𝑡1 . . . 𝑡𝑚 and xs 1 and xs 2 are the variables from ∆ corresponding to ∆1 and ∆2 respectively.

Examples

Below are some examples of with-abstractions and their translations.

postulate
A : Set
_+_ : A → A → A
T : A → Set
mkT : ∀ x → T x
P : ∀ x → T x → Set

-- the type A of the with argument has no free variables, so the with
-- argument will come first
f1 : (x y : A) (t : T (x + y)) → T (x + y)
f1 x y t with x + y
f1 x y t | w = {!!}

-- Generated with function


f-aux1 : (w : A) (x y : A) (t : T w) → T w
f-aux1 w x y t = {!!}
(continues on next page)

3.43. With-Abstraction 181


Agda User Manual, Release 2.6.2

(continued from previous page)

-- x and p are not needed to type the with argument, so the context
-- is reordered with only y before the with argument
f2 : (x y : A) (p : P y (mkT y)) → P y (mkT y)
f2 x y p with mkT y
f2 x y p | w = {!!}

f-aux2 : (y : A) (w : T y) (x : A) (p : P y w) → P y w
f-aux2 y w x p = {!!}

postulate
H : ∀ x y → T (x + y) → Set

-- Multiple with arguments are always inserted together, so in this case


-- t ends up on the left since it’s needed to type h and thus x + y isn’t
-- abstracted from the type of t
f3 : (x y : A) (t : T (x + y)) (h : H x y t) → T (x + y)
f3 x y t h with x + y | h
f3 x y t h | w1 | w2 = {! t : T (x + y), goal : T w1 !}

f-aux3 : (x y : A) (t : T (x + y)) (h : H x y t) (w1 : A) (w2 : H x y t) → T w1


f-aux3 x y t h w1 w2 = {!!}

-- But earlier with arguments are abstracted from the types of later ones
f4 : (x y : A) (t : T (x + y)) → T (x + y)
f4 x y t with x + y | t
f4 x y t | w1 | w2 = {! t : T (x + y), w2 : T w1 , goal : T w1 !}

f-aux4 : (x y : A) (t : T (x + y)) (w1 : A) (w2 : T w1 ) → T w1


f-aux4 x y t w1 w2 = {!!}

Ill-typed with-abstractions

As mentioned above, generalisation does not always produce well-typed results. This happens when you abstract over
a term that appears in the type of a subterm of the goal or argument types. The simplest example is abstracting over
the first component of a dependent pair. For instance,

postulate
A : Set
B : A → Set
H : (x : A) → B x → Set

bad-with : (p : Σ A B) → H (fst p) (snd p)


bad-with p with fst p
... | _ = {!!}

Here, generalising over fst p results in an ill-typed application H w (snd p) and you get the following type
error:

fst p != w of type A
when checking that the type (p : Σ A B) (w : A) → H w (snd p) of
the generated with function is well-formed

This message can be a little difficult to interpret since it only prints the immediate problem (fst p != w) and the
full type of the with-function. To get a more informative error, pointing to the location in the type where the error is,

182 Chapter 3. Language Reference


Agda User Manual, Release 2.6.2

you can copy and paste the with-function type from the error message and try to type check it separately.

3.44 Without K

The option --without-K adds some restrictions to Agda’s typechecking algorithm in order to ensure compatability
with versions of type theory that do not support UIP (uniqueness of identity proofs), such as HoTT (homotopy type
theory).
The option --with-K can be used to override a global --without-K in a file, by adding a pragma
{-# OPTIONS --with-K #-}. This option is enabled by default.

3.44.1 Restrictions on pattern matching

When the option --without-K is enabled, then Agda only accepts certain case splits. More specifically, the uni-
fication algorithm for checking case splits cannot make use of the deletion rule to solve equations of the form x =
x.
For example, the obvious implementation of the K rule is not accepted:

K : {A : Set} {x : A} (P : x ≡ x → Set) →
P refl → (x≡x : x ≡ x) → P x≡x
K P p refl = p

Pattern matching with the constructor refl on the argument x≡x causes x to be unified with x, which fails because
the deletion rule cannot be used when --without-K is enabled.
On the other hand, the obvious implementation of the J rule is accepted:

J : {A : Set} (P : (x y : A) → x ≡ y → Set) →
((x : A) → P x x refl) → (x y : A) (x≡y : x ≡ y) → P x y x≡y
J P p x .x refl = p x

Pattern matching with the constructor refl on the argument x≡y causes x to be unified with y. The same applies to
Christine Paulin-Mohring’s version of the J rule:

J´ : {A : Set} {x : A} (P : (y : A) → x ≡ y → Set) →
P x refl → (y : A) (x≡y : x ≡ y) → P y x≡y
J´ P p ._ refl = p

For more details, see Jesper Cockx’s PhD thesis Dependent Pattern Matching and Proof-Relevant Unification [Cockx
(2017)].

3.44.2 Restrictions on termination checking

When --without-K is enabled, Agda’s termination checker restricts structural descent to arguments ending in data
types or Size. Likewise, guardedness is only tracked when result type is data or record type:

data ⊥ : Set where

mutual
data WOne : Set where wrap : FOne → WOne
FOne = ⊥ → WOne

(continues on next page)

3.44. Without K 183


Agda User Manual, Release 2.6.2

(continued from previous page)


postulate iso : WOne ≡ FOne

noo : (X : Set) → (WOne ≡ X) → X → ⊥


noo .WOne refl (wrap f) = noo FOne iso f

noo is rejected since at type X the structural descent f < wrap f is discounted --without-K:

data Pandora : Set where


C : ∞ ⊥ → Pandora

postulate foo : ⊥ ≡ Pandora

loop : (A : Set) → A ≡ Pandora → A


loop .Pandora refl = C (♯ (loop ⊥ foo))

loop is rejected since guardedness is not tracked at type A --without-K.


See issues #1023, #1264, #1292.

3.44.3 Restrictions on universe levels

When --without-K is enabled, some indexed datatypes must be defined in a higher universe level. In particular,
the types of all indices should fit in the sort of the datatype.
For example, usually (i.e. --with-K) Agda allows the following definition of equality:

data _≡0 _ {l } {A : Set l } (x : A) : A → Set where


refl : x ≡0 x

However, with --without-K it must be defined at a higher universe level:

data _≡´_ {l } {A : Set l } : A → A → Set l where


refl : {x : A} → x ≡´ x

184 Chapter 3. Language Reference


CHAPTER 4

Tools

4.1 Automatic Proof Search (Auto)

Agda supports (since version 2.2.6) the command Auto, that searches for type inhabitants and fills a hole when one
is found. The type inhabitant found is not necessarily unique.
Auto can be used as an aid when interactively constructing terms in Agda. In a system with dependent types it can be
meaningful to use such a tool for finding fragments of, not only proofs, but also programs. For instance, giving the
type signature of the map function over vectors, you will get the desired function as the first solution.
The tool is based on a term search implementation independent of Agda called Agsy. Agsy is a general purpose search
algorithm for a dependently typed language similar to Agda. One should not expect it to handle large problems of any
particular kind, but small enough problems of almost any kind.
Any solution coming from Auto is checked by Agda. Also, the main search algorithm has a timeout mechanism.
Therefore, there is little harm in trying Auto and it might save you key presses.

4.1.1 Usage

The tool is invoked by placing the cursor on a hole and choosing Auto in the goal menu or pressing C-c C-a. Agsy’s
behaviour can be changed by using various options which are passed directly in the hole.

Option Meaning
-t N Set timeout to N seconds
-c Allow Agsy to use case-split
-d Attempt to disprove the goal
ID Use definition ID as a hint
-m Use the definitions in the current module as hints
-r Use the unqualified definitions in scope as hints
-l List up to ten solutions, does not commit to any
-s N Commit to the N th solution

185
Agda User Manual, Release 2.6.2

Giving no arguments is fine and results in a search with default parameters. The search carries on until either a (not
necessarily unique) solution is found, the search space is fully (and unsuccessfully) explored or it times out (one
second by default). Here follows a list of the different modes and parameters.

Case split

Auto normally only tries to find a term that could replace the current hole. However, if the hole constitutes the entire
RHS of the clause (same as for the make-case command), you can instruct Auto to try case splitting by writing (since
version 2.2.8) -c.
Note that if a solution is found the whole file will be reloaded (as for make-case) resulting in a delay. Case splitting
cannot yet be combined with -l or -s <n>.

Equality reasoning

If the constants _≡_ begin_ _≡⟨_⟩_ _ sym cong from the standard library are in scope, then Auto will do
equality reasoning using these constructs. However, it will not do anything more clever than things like not nesting
several sym or cong. Hence long chains of equalities should not be expected and required arithmetical rules have to
be given as hints.

Hints

Auto does not by default try using constants in scope. If there is a lemma around that might help in constructing the
term you can include it in the search by giving hints. There are two ways of doing this. One way is to provide the exact
list of constants to include. Such a list is given by writing a number of constant names separated by space: <hint1>
<hint2> ....
The other way is to write -m. This includes all constants in scope which are defined or postulated in the innermost
module surrounding the current hole. It is also possible to combine -m with a list of named constants (not included by
-m).
There are a few exceptions to what you have to specify as hints:
• Datatypes and constants that can be deduced by unifying the two sides of an equality constraint can be omitted.
E.g., if the constraint ? = List A occurs during the search, then refining ? to List ... will happen without
having to provide List as a hint. The constants that you can leave out overlap more or less with the ones
appearing in hidden arguments, i.e. you wouldn’t have written them when giving the term by hand either.
• Constructors and projection functions are automatically tried, so should never be given as hints.
• Recursive calls, although currently only the function itself, not all functions in the same mutual block.

Timeout

The timeout is one second by default but can be changed by adding -t <n> to the parameters, where <n> is the
number of seconds.

Listing and choosing among several solutions

Normally, Auto replaces the hole with the first solution found. If you are not happy with that particular solution, you
can list the ten (at most) first solutions encountered by including the flag -l.

186 Chapter 4. Tools


Agda User Manual, Release 2.6.2

You can then pick a particular solution by writing -s <n> where <n> is the number of solutions to skip (as well as
the number appearing before the solution in the list). The options -l and -s <n> can be combined to list solutions
other than the ten first ones.

Disproving

If you are uncertain about the validity of what you are trying to prove, you can use Auto to try to find a counterproof.
The flag -d makes Auto negate the current goal and search for a term disproving it. If such a term is found, it will be
displayed in the info buffer. The flag -d can be combined with -l and -l -s <n>.

Auto refine / suggest

There is a special mode for searching (part of) the scope of constants for possible refinement candidates. The flag -r
chooses this mode. By default all constants which are in scope unqualified are included.
The constants that matches the current goal are sorted in order of how many constructs their result type contains. This
means that the constants which in some sense match the goal most specifically will appear first and the most general
ones last. By default, Auto will present a list of candidates, rather than refining using the topmost constant. To select
one of them for refinement, combine -r with -s <n>. In order to list constants other than the ten first ones, write -r
-l -s <n>.
The auto refine feature has little to do with the rest of the Auto tool. If it turns out to be useful it could be improved
and made into a separate Emacs mode command.

Dependencies between meta variables

If the goal type or type of local variables contain meta variables, then the constraints for these are also included in
the search. If a solution is found it means that Auto has also found solutions for the occurring meta variables. Those
solutions will be inserted into your file along with that of the hole from where you called Auto. Also, any unsolved
equality constraints that contain any of the involved meta variables are respected in the search.

4.1.2 Limitations

• Irrelevance is not yet respected. Agsy will happily use a parameter marked as irrelevant and does not disregard
irrelevant arguments when comparing terms.
• Records that lack a constructor name are still deconstructed when case splitting, but the name of the record type
is used instead of a constructor name in the resulting pattern.
• Literals representing natural numbers are supported (but any generated natural number will be given in con-
structor form). Apart from this, literals are not supported.
• Primitive functions are not supported.
• Copatterns are not supported.
• Termination checking for recursive calls is done locally, so a non-terminating set of clauses might be sent back
to Agda.
• Agsy currently does not automatically pick a datatype when instantiating types. A frequently occurring situation
is when you try to disprove a generic property. Then Agsy must come up with a particular type as part of the
disproof. You can either fix your generic type to e.g. Nat or Fin n (for an arbitrary n if you wish), or you
give Nat or Fin as a hint to the search.
• Case split mode currently does not do case on expressions (with).

4.1. Automatic Proof Search (Auto) 187


Agda User Manual, Release 2.6.2

• Case split mode sometimes gives a unnecessarily complex RHS for some clause when the solution consists of
several clauses.
• Agsy has universe subtyping, so sometimes suggests solutions not accepted by Agda.
• Universe polymorphism is only partially supported. Agsy may fail when trying to construct universe polymor-
phic definitions, but will probably succeed (with respect to this) when constructing terms which refer to, or
whose type is defined in terms of, universe polymorphic definitions.
• In case split and disproving modes, the current goal may not depend on any other meta variables. For disproving
mode this means that there may be implicitly universally quantified but not existentially quantified stuff.
• Searching for simultaneous solutions of several holes does not combine well with parameterised modules and
recursive calls.

4.1.3 User feedback

When sending bug reports, please use Agda’s bug tracker. Apart from that, receiving nice examples (via the bug
tracker) would be much appreciated. Both such examples which Auto does not solve, but you have a feeling it’s not
larger than for that to be possible. And examples that Auto only solves by increasing timeout. The examples sent in
will be used for tuning the heuristics and hopefully improving the performance.

4.2 Command-line options

4.2.1 Command-line options

Agda accepts the following options.

General options

--help[={TOPIC}], -?[{TOPIC}]
Show basically this help, or more help about TOPIC. Current topics available: warning.
--interaction
For use with the Emacs mode (no need to invoke yourself).
--interaction-json
New in version 2.6.1.
For use with other editors such as Atom (no need to invoke yourself).
--interactive, -I
Start in interactive mode (no longer supported).
--no-projection-like
New in version 2.6.1.
Turn off the analysis whether a type signature likens that of a projection.
Projection-likeness is an optimization that reduces the size of terms by dropping parameter-like reconstructible
function arguments. Thus, it is advisable to leave this optimization on, the flag is meant for debugging Agda.
--only-scope-checking
Only scope-check the top-level module, do not type-check it (see Quicker generation without typechecking).
--version, -V
Show version number.

188 Chapter 4. Tools


Agda User Manual, Release 2.6.2

Compilation

See Compilers for backend-specific options.


--compile-dir={DIR}
Set DIR as directory for compiler output (default: the project root).
--no-main
Do not treat the requested module as the main module of a program when compiling.
--with-compiler={PATH}
Set PATH as the executable to call to compile the backend’s output (default: ghc for the GHC backend).

Generating highlighted source code

--count-clusters
Count extended grapheme clusters when generating LaTeX code (see Counting Extended Grapheme Clusters).
--css={URL}
Set URL of the CSS file used by the HTML files to URL (can be relative).
--dependency-graph={FILE}
Generate a Dot file FILE with a module dependency graph.
--html
Generate HTML files with highlighted source code (see Generating HTML).
--html-dir={DIR}
Set directory in which HTML files are placed to DIR (default: html).
--html-highlight=[code,all,auto]
Whether to highlight non-Agda code as comments in generated HTML files (default: all; see Generating
HTML).
--latex
Generate LaTeX with highlighted source code (see Generating LaTeX).
--latex-dir={DIR}
Set directory in which LaTeX files are placed to DIR (default: latex).
--vim
Generate Vim highlighting files.

Imports and libraries

(see Library Management)


--ignore-all-interfaces
Ignore all interface files, including builtin and primitive modules; only use this if you know what you are doing!
--ignore-interfaces
Ignore interface files (re-type check everything, except for builtin and primitive modules).
--include-path={DIR}, -i={DIR}
Look for imports in DIR.
--library={DIR}, -l={LIB}
Use library LIB.

4.2. Command-line options 189


Agda User Manual, Release 2.6.2

--library-file={FILE}
Use {FILE} instead of the standard libraries file.
--local-interfaces
New in version 2.6.1.
Read and write interface files next to the Agda files they correspond to (i.e. do not attempt to regroup them in a
_build/ directory at the project’s root).
--no-default-libraries
Don’t use default library files.
--no-libraries
Don’t use any library files.

4.2.2 Command-line and pragma options

The following options can also be given in .agda files using the OPTIONS pragma.

Caching

--caching, --no-caching
Enable [disable] caching of typechecking (default).
Default: --caching

Printing and debugging

--no-unicode
Don’t use unicode characters to print terms.
--show-implicit
Show implicit arguments when printing.
--show-irrelevant
Show irrelevant arguments when printing.
--verbose={N}, -v={N}
Set verbosity level to N.

Copatterns and projections

--copatterns, --no-copatterns
Enable [disable] definitions by copattern matching (see Copatterns).
Default: --copatterns
--postfix-projections
Make postfix projection notation the default.

Experimental features

--confluence-check, --local-confluence-check
New in version 2.6.1.
Enable optional (global or local) confluence checking of REWRITE rules (see Confluence checking).

190 Chapter 4. Tools


Agda User Manual, Release 2.6.2

--cubical
Enable cubical features. Turns on --without-K (see Cubical).
--experimental-irrelevance
Enable potentially unsound irrelevance features (irrelevant levels, irrelevant data matching) (see Irrelevance).
--injective-type-constructors
Enable injective type constructors (makes Agda anti-classical and possibly inconsistent).
--rewriting
Enable declaration and use of REWRITE rules (see Rewriting).
--allow-exec
Enable system calls during type checking (see Reflection).

Errors and warnings

--allow-incomplete-matches
New in version 2.6.1.
Succeed and create interface file regardless of incomplete pattern-matching definitions. See, also, the
NON_COVERING pragma.
--allow-unsolved-metas
Succeed and create interface file regardless of unsolved meta variables (see Metavariables).
--no-positivity-check
Do not warn about not strictly positive data types (see Positivity Checking).
--no-termination-check
Do not warn about possibly nonterminating code (see Termination Checking).
--warning={GROUP|FLAG}, -W {GROUP|FLAG}
Set warning group or flag (see Warnings).

Pattern matching and equality

--exact-split, --no-exact-split
Require [do not require] all clauses in a definition to hold as definitional equalities unless marked CATCHALL
(see Case trees).
Default: --no-exact-split
--no-eta-equality
Default records to no-eta-equality (see Eta-expansion).
--no-flat-split
New in version 2.6.1.
Disable pattern matching on @♭ arguments (see Pattern Matching on @♭).
--no-pattern-matching
Disable pattern matching completely.
--with-K
Overrides a global --without-K in a file (see Without K).
--without-K
Disables definitions using Streicher’s K axiom (see Without K).

4.2. Command-line options 191


Agda User Manual, Release 2.6.2

--keep-pattern-variables
New in version 2.6.1.
Prevent interactive case splitting from replacing variables with dot patterns (see Dot patterns).

Search depth and instances

--instance-search-depth={N}
Set instance search depth to N (default: 500; see Instance Arguments),
--inversion-max-depth={N}
Set maximum depth for pattern match inversion to N (default: 50). Should only be needed in pathological cases.
--termination-depth={N}
Allow termination checker to count decrease/increase upto N (default: 1; see Termination Checking).
--overlapping-instances, --no-overlapping-instances
Consider [do not consider] recursive instance arguments during pruning of instance candidates.
Default: --no-overlapping-instances

Other features

--double-check
Enable double-checking of all terms using the internal typechecker.
--guardedness, --no-guardedness
Enable [disable] constructor-based guarded corecursion (see Coinduction).
The option --guardedness is inconsistent with sized types and it is turned off by --safe (but can be turned
on again, as long as not also --sized-types is on).
Default: --guardedness
--irrelevant-projections, --no-irrelevant-projections
New in version 2.5.4.
Enable [disable] projection of irrelevant record fields (see Irrelevance). The option
--irrelevant-projections makes Agda inconsistent.
Default (since version 2.6.1): --no-irrelevant-projections
--auto-inline
Turn on automatic compile-time inlining. See The INLINE and NOINLINE pragmas for more information.
--no-auto-inline
Disable automatic compile-time inlining (default). Only definitions marked INLINE will be inlined.
--no-fast-reduce
Disable reduction using the Agda Abstract Machine.
--call-by-name
Disable call-by-need evaluation in the Agda Abstract Machine.
--no-forcing
Disable the forcing optimisation. Since Agda 2.6.1 is a pragma option.
--no-print-pattern-synonyms
Always expand Pattern Synonyms during printing. With this option enabled you can use pattern synonyms freely,
but Agda will not use any pattern synonyms when printing goal types or error messages, or when generating
patterns for case splits.

192 Chapter 4. Tools


Agda User Manual, Release 2.6.2

--no-syntactic-equality
Disable the syntactic equality shortcut in the conversion checker.
--safe
Disable postulates, unsafe OPTIONS pragmas and primTrustMe. Turns off --sized-types and
--guardedness (at most one can be turned back on again) (see Safe Agda).
--sized-types, --no-sized-types
Enable [disable] sized types (see Sized Types).
The option --sized-types is inconsistent with constructor-based guarded corecursion and it is turned off
by --safe (but can be turned on again, as long as not also --guardedness is on).
Default: --sized-types
--type-in-type
Ignore universe levels (this makes Agda inconsistent; see type-in-type).
--omega-in-omega
Enable typing rule Set𝜔 : Set𝜔 (this makes Agda inconsistent; see omega-in-omega).
--universe-polymorphism, --no-universe-polymorphism
Enable [disable] universe polymorphism (see Universe Levels).
Default: --universe-polymorphism
--cumulativity, --no-cumulativity
New in version 2.6.1.
Enable [disable] cumulative subtyping of universes, i.e. if A : Set i then also A : Set j for all j >= i. Implies
–subtyping.
Default: --no-cumulativity
--subtyping, --no-subtyping
New in version 2.6.1.
Enable [disable] subtyping rules globally, including subtyping for irrelevance, erasure (@0) and flat (@♭) modal-
ities.
Default: --no-subtyping
--no-import-sorts
New in version 2.6.2.
Disable the implicit statement open import Agda.Primitive using (Set; Prop) at the start of each top-level Agda
module.

Warnings

The -W or --warning option can be used to disable or enable different warnings. The flag -W error (or
--warning=error) can be used to turn all warnings into errors, while -W noerror turns this off again.
A group of warnings can be enabled by -W {group}, where group is one of the following:
all
All of the existing warnings.
warn.
Default warning level
ignore
Ignore all warnings.

4.2. Command-line options 193


Agda User Manual, Release 2.6.2

The command agda --help=warning provides information about which warnings are turned on by default.
Individual warnings can be turned on and off by -W {Name} and -W {noName} respectively. The flags available
are:
AbsurdPatternRequiresNoRHS
RHS given despite an absurd pattern in the LHS.
CantGeneralizeOverSorts
Attempt to generalize over sort metas in ‘variable’ declaration.
CoInfectiveImport
Importing a file not using e.g. --safe from one which does.
CoverageIssue
Failed coverage checks.
CoverageNoExactSplit
Failed exact split checks.
DeprecationWarning
Feature deprecation.
EmptyAbstract
Empty abstract blocks.
EmptyInstance
Empty instance blocks.
EmptyMacro
Empty macro blocks.
EmptyMutual
Empty mutual blocks.
EmptyPostulate
Empty postulate blocks.
EmptyPrimitive
Empty primitive blocks.
EmptyPrivate
Empty private blocks.
EmptyRewritePragma
Empty REWRITE pragmas.
IllformedAsClause
Illformed as-clauses in import statements.
InfectiveImport
Importing a file using e.g. :option;‘–cubical‘ into one which doesn’t.
InstanceNoOutputTypeName
Instance arguments whose type does not end in a named or variable type are never considered by instance search.
InstanceArgWithExplicitArg
Instance arguments with explicit arguments are never considered by instance search.
InstanceWithExplicitArg
Instance declarations with explicit arguments are never considered by instance search.
InvalidCatchallPragma
CATCHALL pragmas before a non-function clause.

194 Chapter 4. Tools


Agda User Manual, Release 2.6.2

InvalidNoPositivityCheckPragma
No positivity checking pragmas before non-data‘, record or mutual blocks.
InvalidTerminationCheckPragma
Termination checking pragmas before non-function or mutual blocks.
InversionDepthReached
Inversions of pattern-matching failed due to exhausted inversion depth.
LibUnknownField
Unknown field in library file.
MissingDefinitions
Names declared without an accompanying definition.
ModuleDoesntExport
Names mentioned in an import statement which are not exported by the module in question.
NotAllowedInMutual
Declarations not allowed in a mutual block.
NotStrictlyPositive
Failed strict positivity checks.
OldBuiltin
Deprecated BUILTIN pragmas.
OverlappingTokensWarning
Multi-line comments spanning one or more literate text blocks.
PolarityPragmasButNotPostulates
Polarity pragmas for non-postulates.
PragmaCompiled
COMPILE pragmas not allowed in safe mode.
PragmaCompileErased
COMPILE pragma targeting an erased symbol.
PragmaNoTerminationCheck
NO_TERMINATION_CHECK pragmas are deprecated.
RewriteMaybeNonConfluent
Failed confluence checks while computing overlap.
RewriteNonConfluent
Failed confluence checks while joining critical pairs.
SafeFlagNonTerminating
NON_TERMINATING pragmas with the safe flag.
SafeFlagNoPositivityCheck
NO_POSITIVITY_CHECK pragmas with the safe flag.
SafeFlagNoUniverseCheck
NO_UNIVERSE_CHECK pragmas with the safe flag.
SafeFlagPolarity
POLARITY pragmas with the safe flag.
SafeFlagPostulate
postulate blocks with the safe flag

4.2. Command-line options 195


Agda User Manual, Release 2.6.2

SafeFlagPragma
Unsafe OPTIONS pragmas with the safe flag.
SafeFlagTerminating
TERMINATING pragmas with the safe flag.
SafeFlagWithoutKFlagPrimEraseEquality
primEraseEquality used with the safe and without-K flags.
ShadowingInTelescope
Repeated variable name in telescope.
TerminationIssue
Failed termination checks.
UnknownFixityInMixfixDecl
Mixfix names without an associated fixity declaration.
UnknownNamesInFixityDecl
Names not declared in the same scope as their syntax or fixity declaration.
UnknownNamesInPolarityPragmas
Names not declared in the same scope as their polarity pragmas.
UnreachableClauses
Unreachable function clauses.
UnsolvedConstraints
Unsolved constraints.
UnsolvedInteractionMetas
Unsolved interaction meta variables.
UnsolvedMetaVariables
Unsolved meta variables.
UselessAbstract
abstract blocks where they have no effect.
UselessInline
INLINE pragmas where they have no effect.
UselessInstance
instance blocks where they have no effect.
UselessPrivate
private blocks where they have no effect.
UselessPublic
public blocks where they have no effect.
WithoutKFlagPrimEraseEquality
primEraseEquality used with the without-K flags.
WrongInstanceDeclaration
Terms marked as eligible for instance search should end with a name.

4.2.3 Examples

Run Agda with all warnings enabled, except for warnings about empty abstract blocks:

196 Chapter 4. Tools


Agda User Manual, Release 2.6.2

agda -W all --warning=noEmptyAbstract file.agda

Run Agda on a file which uses the standard library. Note that you must have already created a libraries file as
described in Library Management

agda -l standard-library -i. file.agda

(Or if you have added standard-library to your defaults file, simply agda file.agda)

4.2.4 Consistency checking of options used

Agda checks that options used in imported modules are consistent with each other.
An infective option is an option that if used in one module, must be used in all modules that depend on this module.
The following options are infective:
• --cubical
• --prop
• --rewriting
A coinfective option is an option that if used in one module, must be used in all modules that this module depends on.
The following options are coinfective:
• --safe
• --without-K
• --no-universe-polymorphism
• --no-sized-types
• --no-guardedness
Agda records the options used when generating an interface file. If any of the following options differ when trying to
load the interface again, the source file is re-typechecked instead:
• --termination-depth
• --no-unicode
• --allow-unsolved-metas
• --allow-incomplete-matches
• --no-positivity-check
• --no-termination-check
• --type-in-type
• --omega-in-omega
• --no-sized-types
• --no-guardedness
• --injective-type-constructors
• --prop
• --no-universe-polymorphism
• --irrelevant-projections

4.2. Command-line options 197


Agda User Manual, Release 2.6.2

• --experimental-irrelevance
• --without-K
• --exact-split
• --no-eta-equality
• --rewriting
• --cubical
• --overlapping-instances
• --safe
• --double-check
• --no-syntactic-equality
• --no-auto-inline
• --no-fast-reduce
• --instance-search-depth
• --inversion-max-depth
• --warning
• --allow-exec

4.3 Compilers

• Backends
– GHC Backend
– JavaScript Backend
• Optimizations
– Builtin natural numbers
– Erasable types

See also Foreign Function Interface.

4.3.1 Backends

GHC Backend

The GHC backend translates Agda programs into GHC Haskell programs.

Usage

The backend can be invoked from the command line using the flag --compile:

198 Chapter 4. Tools


Agda User Manual, Release 2.6.2

agda --compile [--compile-dir=<DIR>] [--ghc-flag=<FLAG>] <FILE>.agda

Pragmas

Example

The following “Hello, World!” example requires some Built-ins and uses the Foreign Function Interface:

module HelloWorld where

open import Agda.Builtin.IO


open import Agda.Builtin.Unit
open import Agda.Builtin.String

postulate
putStrLn : String → IO ⊤

{-# FOREIGN GHC import qualified Data.Text.IO as Text #-}


{-# COMPILE GHC putStrLn = Text.putStrLn #-}

main : IO ⊤
main = putStrLn "Hello, World!"

After compiling the example

agda --compile HelloWorld.agda

you can run the HelloWorld program which prints Hello, World!.

Warning: Frequent error when compiling: Float requires the ieee754 haskell library. Usually cabal
install ieee754 in the command line does the trick.

JavaScript Backend

The JavaScript backend translates Agda code to JavaScript code.

Usage

The backend can be invoked from the command line using the flag --js:

agda --js [--js-optimize] [--js-minify] [--compile-dir=<DIR>] <FILE>.agda

The --js-optimize flag makes the generated JavaScript code typically faster and less readable.
The --js-minify flag makes the generated JavaScript code smaller and less readable.

4.3.2 Optimizations

4.3. Compilers 199


Agda User Manual, Release 2.6.2

Builtin natural numbers

Builtin natural numbers are represented as arbitrary-precision integers. The builtin functions on natural numbers are
compiled to the corresponding arbitrary-precision integer functions.
Note that pattern matching on an Integer is slower than on an unary natural number. Code that does a lot of unary
manipulations and doesn’t use builtin arithmetic likely becomes slower due to this optimization. If you find that this
is the case, it is recommended to use a different, but isomorphic type to the builtin natural numbers.

Erasable types

A data type is considered erasable if it has a single constructor whose arguments are all erasable types, or functions
into erasable types. The compilers will erase
• calls to functions into erasable types
• pattern matches on values of erasable type
At the moment the compilers only have enough type information to erase calls of top-level functions that can be seen
to return a value of erasable type without looking at the arguments of the call. In other words, a function call will not
be erased if it calls a lambda bound variable, or the result is erasable for the given arguments, but not for others.
Typical examples of erasable types are the equality type and the accessibility predicate used for well-founded recur-
sion:

data _≡_ {a} {A : Set a} (x : A) : A → Set a where


refl : x ≡ x

data Acc {a} {A : Set a} (_<_ : A → A → Set a) (x : A) : Set a where


acc : (∀ y → y < x → Acc _<_ y) → Acc _<_ x

The erasure means that equality proofs will (mostly) be erased, and never looked at, and functions defined by well-
founded recursion will ignore the accessibility proof.

4.4 Emacs Mode

Agda programs are commonly edited using Emacs which is explained in this section. Other editors with interactive
support for Agda include Atom (agda-mode on Atom), Visual Studio Code (agda-mode on VS Code), and Vim (agda-
vim).
To edit a module in Emacs (assuming you have installed Agda and the Emacs mode properly), open a file ending in .
agda and load it by pressing C-c C-l (other commands are listed under Notation for key combinations below). This
will apply syntax highlighting to the code and display any errors in a separate buffer. Agda uses certain background
colors to indicate specific issues with the code, see Background highlighting below.

4.4.1 Menus

There are two main menus in the system:


• A main menu called Agda2 which is used for global commands.
• A context sensitive menu which appears if you right-click in a hole.
The menus contain more commands than the ones listed above. See global and context sensitive commands.

200 Chapter 4. Tools


Agda User Manual, Release 2.6.2

4.4.2 Configuration

If you want to you can customise the Emacs mode. Just start Emacs and type the following:

M-x load-library RET agda2-mode RET


M-x customize-group RET agda2 RET

If you want some specific settings for the Emacs mode you can add them to agda2-mode-hook. For instance, if
N
you do not want to use the Agda input method (for writing various symbols like ∀≥ →𝜋JK) you can add the following
to your .emacs:

(add-hook 'agda2-mode-hook
'(lambda ()
; If you do not want to use any input method:
(deactivate-input-method)
; (In some versions of Emacs you should use
; inactivate-input-method instead of
; deactivate-input-method.)

Note that, on some systems, the Emacs mode changes the default font of the current frame in order to enable many
Unicode symbols to be displayed. This only works if the right fonts are available, though. If you want to turn off this
feature, then you should customise the agda2-fontset-name variable.
The colors that are used to highlight Agda syntax and errors can be adjusted by typing M-x customize-group
RET agda2-highlight RET in Emacs and following the instructions.

4.4.3 Keybindings

Notation for key combinations

The following notation is used when describing key combinations:


C-c means hitting the c key while pressing the Ctrl key.
M-x means hitting the x key while pressing the Meta key, which is called Alt on many systems. Alternatively one
can type Escape followed by x (in separate key strokes).
RET is the Enter, Return or ←˒ key.
SPC is the space bar.
Commands working with terms or types can be prefixed with C-u to compute without further normalisation, with C-u
C-u to compute normal forms, and C-u C-u C-u to compute weak-head normal forms.

Global commands

C-c C-l Load file. This type-checks the contents of the file, and replaces each occurrence of a question mark ? or
a hole marker {! !} by a freshly created hole.
C-c C-x C-c Compile file. This will compile an Agda program with a main function using a given backend (the
GHC backend is used by default).
C-c C-x C-q Quit, kill the Agda process
C-c C-x C-r Kill and restart the Agda process
C-c C-x C-a Abort a command
C-c C-x C-d Remove goals and highlighting (deactivate)

4.4. Emacs Mode 201


Agda User Manual, Release 2.6.2

C-c C-x C-h Toggle display of hidden arguments


C-c C-x C-i Toggle display of irrelevant arguments
C-c C-= Show constraints
C-c C-s Solve constraints
C-c C-? Show all goals
C-c C-f Move to next goal (forward)
C-c C-b Move to previous goal (backwards)
C-c C-d Infer (deduce) type. The system asks for a term and infers its type. When executed inside a hole, it will
instead take the contents of the hole as input (if any).
C-c C-o Module contents
C-c C-z Search Definitions in Scope
C-c C-n Compute normal form. The system asks for a term which is then evaluated. When executed inside a hole,
it will instead take the contents of the hole as input (if any).
C-u C-c C-n Compute normal form, ignoring abstract
C-u C-u C-c C-n Compute and print normal form of show <expression>
C-c C-x M-; Comment/uncomment rest of buffer
C-c C-x C-s Switch to a different Agda version

Commands in context of a goal

Commands expecting input (for example which variable to case split) will either use the text inside the goal or ask the
user for input.
C-c C-SPC Give (fill goal)
C-c C-r Refine. Checks whether the return type of the expression e in the hole matches the expected type. If so,
the hole is replaced by e { }1 ... { }n, where a sufficient number of new holes have been inserted. If the
hole is empty, then the refine command instead inserts a lambda or constructor (if there is a unique type-correct
choice).
C-c C-m Elaborate and Give (fill goal with normalized expression). Takes the same C-u prefixes as C-c C-n.
C-c C-a Automatic Proof Search (Auto)
C-c C-c Case split. If the cursor is positioned in a hole which denotes the right hand side of a definition, then this
command automatically performs pattern matching on variables of your choice. When given several variables
(separated by spaces) it will case split on the first and then continue by case splitting on the remaining variables
in each newly created clause. When given no variables, it will introduce a new variable if the target type is a
function type, or introduce a new copattern match if the target type is a record type (see Copatterns). When
given the special symbol ., it will expand the ellipsis ... in the clause (see With-Abstraction).
C-c C-h Compute type of helper function and add type signature to kill ring (clipboard)
C-c C-t Goal type
C-c C-e Context (environment)
C-c C-d Infer (deduce) type
C-c C-, Goal type and context. Shows the goal type, i.e. the type expected in the current hole, along with the types
of locally defined identifiers.

202 Chapter 4. Tools


Agda User Manual, Release 2.6.2

C-c C-. Goal type, context and inferred type


C-c C-; Goal type, context and checked term
C-c C-o Module contents
C-c C-n Compute normal form
C-u C-c C-n Compute normal form, ignoring abstract
C-u C-u C-c C-n Compute and print normal form of show <expression>
C-c C-w Why in scope, given a defined name returns how it was brought into scope and its definition

Other commands

TAB Indent current line, cycles between points


S-TAB Indent current line, cycles in opposite direction
M-. Go to definition of identifier under point
Middle mouse button Go to definition of identifier clicked on
M-* Go back (Emacs < 25.1)
M-, Go back (Emacs ≥ 25.1)

4.4.4 Unicode input

How can I write Unicode characters using Emacs?

The Agda Emacs mode comes with an input method for easily writing Unicode characters. Most Unicode character
can be input by typing their corresponding TeX/LaTeX commands, eg. typing \lambda will input 𝜆. Some characters
N
have key bindings which have not been taken from TeX/LaTeX (typing \bN results in being inserted, for instance),
but all bindings start with \.
To see all characters you can input using the Agda input method type M-x describe-input-method RET
Agda or type M-x agda-input-show-translations RET RET (with some exceptions in certain versions
of Emacs).
If you know the Unicode name of a character you can input it using M-x ucs-insert RET (which supports tab-
completion) or C-x 8 RET. Example: Type C-x 8 RET not SPACE a SPACE sub TAB RET to insert the
character “NOT A SUBSET OF” (̸⊂).
(The Agda input method has one drawback: if you make a mistake while typing the name of a character, then you
need to start all over again. If you find this terribly annoying, then you can use Abbrev mode instead. However, note
that Abbrev mode cannot be used in the minibuffer, which is used to give input to many Agda and Emacs commands.)
The Agda input method can be customised via M-x customize-group RET agda-input.

OK, but how can I find out what to type to get the . . . character?

To find out how to input a specific character, eg from the standard library, position the cursor over the character and
type M-x describe-char or C-u C-x =.
For instance, for :: I get the following:

4.4. Emacs Mode 203


Agda User Manual, Release 2.6.2

character: :: (displayed as ::) (codepoint 8759, #o21067, #x2237)


preferred charset: unicode (Unicode (ISO10646))
code point in charset: 0x2237
script: symbol
syntax: w which means: word
category: .:Base, c:Chinese
to input: type "\::" with Agda input method
buffer code: #xE2 #x88 #xB7
file code: #xE2 #x88 #xB7 (encoded by coding system utf-8-unix)
display: by this font (glyph code)
x:-misc-fixed-medium-r-normal--20-200-75-75-c-100-iso10646-1 (#x2237)

Character code properties: customize what to show


name: PROPORTION
general-category: Sm (Symbol, Math)
decomposition: (8759) ('::')

There are text properties here:


fontified t

Here it says that I can type \:: to get a ::. If there is no “to input” line, then you can add a key binding to the Agda
input method by using M-x customize-variable RET agda-input-user-translations.

Show me some commonly used characters

Many common characters have a shorter input sequence than the corresponding TeX command:
• Arrows: \r- for →. You can replace r with another direction: u, d, l. Eg. \d- for ↓. Replace - with = or ==
to get a double and triple arrows.
• Greek letters can be input by \G followed by the first character of the letters Latin name. Eg. \Gl will input 𝜆
while \GL will input Λ.
• Negation: you can get the negated form of many characters by appending n to the name. Eg. while \ni inputs
∋, \nin will input ̸∋.
• Subscript and superscript: you can input subscript or superscript forms by prepending the character with
\_ (subscript) or \^ (superscript). Eg. g\_1 will input g1 . Note that not all characters have a subscript or
superscript counterpart in Unicode.
Note: to introduce multiple characters involving greek letters, subscripts or superscripts, you need to prepend \G, \_
or \^ respectively before each character.
Some characters which were used in this documentation or which are commonly used in the standard library (sorted
by hexadecimal code):

204 Chapter 4. Tools


Agda User Manual, Release 2.6.2

Hex code Character Short key-binding TeX command


00AC ¬ \neg
00D7 × \x \times
𝑠
02E2 \^s
03BB 𝜆 \Gl \lambda
041F PDF TODO
0432 PDF TODO
0435 PDF TODO
0438 PDF TODO
043C PDF TODO
0440 PDF TODO
0442 PDF TODO
1D62 𝑖 \_i
2032 ´ \'1 \prime
𝑛
207F \^n
2081 1 \_1
2082 2 \_2
2083 3 \_3
2084 4 \_4
2096 𝑘 \_k
2098 𝑚 \_m
2099 𝑛 \_n

Hex code Character Short key-binding TeX command


2113 l \ell

4.4. Emacs Mode 205


Agda User Manual, Release 2.6.2

Hex code Character Short key-binding TeX command


2115 N \bN \Bbb{N}
2191 ↑ \u \uparrow
2192 → \r- \to
21A6 ↦ → \r-| \mapsto
2200 ∀ \all \forall
2208 ∈ \in
220B ∋ \ni
220C ̸ ∋ \nin
2218 ∘ \o \circ
2237 :: \::
223C ∼ \~ \sim
2248 ≈ \~~ \approx
2261 ≡ \== \equiv
2264 ≤ \<= \le
2284 ̸ ⊂ \subn
228E ⊎ \u+ \uplus
2294 ⊔ \lub
22A2 ⊢ \|- \vdash
22A4 ⊤ \top
22A5 ⊥ \bot
266D ♭ \b
266F ♯ \#
27E8 ⟨ \<
27E9 ⟩ \>

Hex code Character Short key-binding TeX command


2983 PDF TODO \{{
2984 PDF TODO \}}
2985 PDF TODO \((
2986 PDF TODO \))

Hex code Character Short key-binding TeX command


2C7C 𝑗 \_j

4.4.5 Background highlighting

Agda uses various background colors to indicate specific errors or warnings in your code. Specifically, the following
colors are used:
• A yellow background indicates unsolved metavariables (see Metavariables) or unsolved constraints.
• A light salmon (pink-orange) background indicates an issue with termination or productivity checking (see
Termination Checking).
• A wheat (light yellow) background indicates an issue with coverage checking (see Coverage Checking).
• A peru (brown) background indicates an issue with positivity checking (see Positivity Checking).
• An orange background indicates a type signature with a missing definition.
• A light coral (darker pink) background indicates a fatal warning

206 Chapter 4. Tools


Agda User Manual, Release 2.6.2

• A grey background indicates unreachable or dead code, and for shadowed variable names in telescopes.
• A white smoke (light grey) background indicates a clauses that does not hold definitionally (see Case trees).
• A pink background indicates an issue with confluence checking of rewrite rules (see Confluence checking).

4.5 Literate Programming

Agda supports a limited form of literate programming, i.e. code interspersed with prose, if the corresponding filename
extension is used.

4.5.1 Literate TeX

Files ending in .lagda or .lagda.tex are interpreted as literate TeX files. All code has to appear in code blocks:

Ignored by Agda.

\begin{code}[ignored by Agda]
module Whatever where
-- Agda code goes here
\end{code}

Text outside of code blocks is ignored, as well as text right after \begin{code}, on the same line.
Agda finds code blocks by looking for the first instance of \begin{code} that is not preceded on the same line by
% or \ (not counting \ followed by any code point), then (starting on the next line) the first instance of \end{code}
that is preceded by nothing but spaces or tab characters (\t), and so on (always starting on the next line). Note that
Agda does not try to figure out if, say, the LaTeX code changes the category code of %.
If you provide a suitable definition for the code environment, then literate Agda files can double as LaTeX document
sources. Example definition:

\usepackage{fancyvrb}

\DefineVerbatimEnvironment
{code}{Verbatim}
{} % Add fancy options here if you like.

The LaTeX backend or the preprocessor lhs2TeX can also be used to produce LaTeX code from literate Agda files. See
Known pitfalls and issues for how to make LaTeX accept Agda files using the UTF-8 character encoding.

4.5.2 Literate reStructuredText

Files ending in .lagda.rst are interpreted as literate reStructuredText files. Agda will parse code following a line
ending in ::, as long as that line does not start with ..:

This line is ordinary text, which is ignored by Agda.

::

module Whatever where


-- Agda code goes here

Another non-code line.


(continues on next page)

4.5. Literate Programming 207


Agda User Manual, Release 2.6.2

(continued from previous page)


::
.. This line is also ignored

reStructuredText source files can be turned into other formats such as HTML or LaTeX using Sphinx.
• Code blocks inside an rST comment block will be type-checked by Agda, but not rendered.
• Code blocks delimited by .. code-block:: agda or .. code-block:: lagda will be rendered,
but not type-checked by Agda.
• All lines inside a codeblock must be further indented than the first line of the code block.
• Indentation must be consistent between code blocks. In other words, the file as a whole must be a valid Agda
file if all the literate text is replaced by white space.

4.5.3 Literate Markdown

Files ending in .lagda.md are interpreted as literate Markdown files. Code blocks start with ``` or ```agda on
its own line, and end with ```, also on its own line:
This line is ordinary text, which is ignored by Agda.

```
module Whatever where
-- Agda code goes here
```

Here is another code block:

```agda
data N : Set where
zero : N
suc : N→ N
```

Markdown source files can be turned into many other formats such as HTML or LaTeX using PanDoc.
• Code blocks which should be type-checked by Agda but should not be visible when the Markdown is rendered
may be enclosed in HTML comment delimiters (<!-- and -->).
• Code blocks which should be ignored by Agda, but rendered in the final document may be indented by four
spaces.
• Note that inline code fragments are not supported due to the difficulty of interpreting their indentation level with
respect to the rest of the file.

4.5.4 Literate Org

Files ending in .lagda.org are interpreted as literate Org files. Code blocks are surrounded by two lines including
only `#+begin_src agda2` and `#+end_src` (case insensitive).
This line is ordinary text, which is ignored by Agda.

#+begin_src agda2
module Whatever where
-- Agda code goes here
(continues on next page)

208 Chapter 4. Tools


Agda User Manual, Release 2.6.2

(continued from previous page)


#+end_src

Another non-code line.

• Code blocks which should be ignored by Agda, but rendered in the final document may be placed in source
blocks without the agda2 label.

4.6 Generating HTML

To generate highlighted, hyperlinked web pages from source code, run the following command in a shell:

$ agda --html --html-dir={output directory} {root module}

You can change the way in which the code is highlighted by providing your own CSS file instead of the default,
included one (use the --css option).
You can also highlight all the occurrences of the symbol your mouse is hovering in the HTML by adding the
--highlight-occurrences option. The default behaviour only highlight the single symbol your mouse is hov-
ering. Note that this feature may cause browser performance problem, please enable it carefully (not recommended
for huge files).
If you’re using Literate Agda with Markdown or reStructedText and you want to highlight your Agda codes with
Agda’s HTML backend and render the rest of the content (let’s call it “literate” part for convenience) with some
another renderer, you can use the --html-highlight=code option, which makes the Agda compiler:
• not wrapping the literate part into <a class="Background"> tags
• not wrapping the generated document with a <html> tag, which means you’ll have to specify the CSS location
somewhere else, like <link rel="stylesheet" type="text/css" href="Agda.css">
• converting <a class="Markup"> tags into <pre class="agda-code"> tags that wrap the complete
Agda code block below
• generating files with extension as-is (i.e. .lagda.md becomes .md, .lagda.rst becomes .rst)
• for reStructuredText, a .. raw:: html will be inserted before every code blocks
This will affect all the files involved in one compilation, making pure Agda code files rendered without
HTML footer/header as well. To use code with literate Agda files and all with pure Agda files, use
--html-highlight=auto, which means auto-detection.

4.6.1 Options

--html-dir=directory Changes the directory where the output is placed to directory. Default: html.
--css=URL The CSS file used by the HTML files (URL can be relative).
--html-highlight=[code,all,auto] Highlight Agda code only or everything in the generated HTML files.
Default: all.

4.7 Generating LaTeX

An experimental LaTeX backend was added in Agda 2.3.2. It can be used as follows:

4.6. Generating HTML 209


Agda User Manual, Release 2.6.2

$ agda --latex {file}.lagda


$ cd latex
$ {latex-compiler} {file}.tex

where latex-compiler could be pdflatex, xelatex or lualatex, and file.lagda is a literate Agda
TeX file (it could also be called file.lagda.tex). The source file is expected to import the LaTeX package agda
by including the code \usepackage{agda} (possibly with some options). Unlike the HTML backend only the
top-most module is processed. Imported modules can be processed by invoking agda --latex manually on each
of them.
The LaTeX backend checks if agda.sty is found by the LaTeX environment. If it isn’t, a default agda.sty is
copied into the LaTeX output directory (by default latex). Note that the appearance of typeset code can be modified
by overriding definitions from agda.sty.

4.7.1 Known pitfalls and issues

• Unicode characters may not be typeset properly out of the box. How to address this problem depends on what
LaTeX engine is used.
– pdfLaTeX:
The pdfLaTeX program does not by default understand the UTF-8 character encoding. You can tell it to
treat the input as UTF-8 by using the inputenc package:

\usepackage[utf8]{inputenc}

If the inputenc package complains that some Unicode character is “not set up for use with LaTeX”, then
you can give your own definition. Here is one example:

\usepackage{newunicodechar}
\newunicodechar{𝜆}{\ensuremath{\mathnormal\lambda}}
\newunicodechar{←}{\ensuremath{\mathnormal\from}}
\newunicodechar{→}{\ensuremath{\mathnormal\to}}
\newunicodechar{∀}{\ensuremath{\mathnormal\forall}}

– XeLaTeX or LuaLaTeX:
It can sometimes be easier to use LuaLaTeX or XeLaTeX. When these engines are used it might suffice to
choose a suitable font, as long as it contains all the right symbols in all the right shapes. If it does not, then
\newunicodechar can be used as above. Here is one example:

\usepackage{unicode-math}
\setmathfont{XITS Math}

\usepackage{newunicodechar}
\newunicodechar{𝜆}{\ensuremath{\mathnormal\lambda}}

• If < and > are typeset like ¡ and ¿, then the problem might be that you are using pdfLaTeX and have not selected
a suitable font encoding.
Possible workaround:

\usepackage[T1]{fontenc}

• If a regular text font is used, then -- might be typeset as an en dash (–).


Possible workarounds:

210 Chapter 4. Tools


Agda User Manual, Release 2.6.2

– Use a monospace font.


– Turn off ligatures. With pdfLaTeX the following code (which also selects a font encoding, and only turns
off ligatures for character sequences starting with -) might work:

\usepackage[T1]{fontenc}
\usepackage{microtype}
\DisableLigatures[-]{encoding=T1}

With LuaLaTeX or XeLaTeX the following code (which also selects a font) might work:

\usepackage{fontspec}
\defaultfontfeatures[\rmfamily]{}
\setmainfont{Latin Modern Roman}

Note that you might not want to turn off all kinds of ligatures in the entire document. See the examples
below for information on how to set up special font families without TeX ligatures that are only used for
Agda code.
• The unicode-math package and older versions of the polytable package are incompatible, which can result in
errors in generated LaTeX code.
Possible workaround: Download a more up-to-date version of polytable and put it together with the generated
files or install it globally.

4.7.2 Options

The following command-line options change the behaviour of the LaTeX backend:
--latex-dir={directory} Changes the output directory where agda.sty and the output .tex file are
placed to directory. Default: latex.
--only-scope-checking Generates highlighting without typechecking the file. See Quicker generation without
typechecking.
--count-clusters Count extended grapheme clusters when generating LaTeX code. This option can be given
in OPTIONS pragmas. See Counting Extended Grapheme Clusters.
The following options can be given when loading agda.sty by using \usepackage[options]{agda}:
bw Colour scheme which highlights in black and white.
conor Colour scheme similar to the colours used in Epigram 1.
references Enables inline typesetting of referenced code.
links Enables hyperlink support.

4.7.3 Quicker generation without typechecking

A faster variant of the backend is available by invoking QuickLaTeX from the Emacs mode, or using agda
--latex --only-scope-checking. When this variant of the backend is used the top-level module is not
type-checked, only scope-checked. Note that this can affect the generated document. For instance, scope-checking
does not resolve overloaded constructors.
If the module has already been type-checked successfully, then this information is reused; in this case QuickLaTeX
behaves like the regular LaTeX backend.

4.7. Generating LaTeX 211


Agda User Manual, Release 2.6.2

4.7.4 Features

Vertical space

Code blocks are by default surrounded by vertical space. Use \AgdaNoSpaceAroundCode{} to avoid this vertical
space, and \AgdaSpaceAroundCode{} to reenable it.
Note that, if \AgdaNoSpaceAroundCode{} is used, then empty lines before or after a code block will not neces-
sarily lead to empty lines in the generated document. However, empty lines inside the code block do (by default, with
or without \AgdaNoSpaceAroundCode{}) lead to empty lines in the output. The height of such empty lines can
be controlled by the length \AgdaEmptySkip, which by default is \abovedisplayskip.

Alignment

Tokens preceded by two or more space characters, as in the following example, are aligned in the typeset output:

\begin{code}
data N
: Set where
zero : N
suc : N N→

_+_ : N→N→N
zero + n = n
suc m + n = suc (m + n)
\end{code}

In the case of the first token on a line a single space character sometimes suffices to get alignment. A constraint on the
indentation of the first token t on a line is determined as follows:
• Let T be the set containing every previous token (in any code block) that is either the initial token on its line or
preceded by at least one whitespace character.
• Let S be the set containing all tokens in T that are not shadowed by other tokens in T. A token t1 is shadowed
by t2 if t2 is further down than t1 and does not start to the right of t1 .
• Let L be the set containing all tokens in S that start to the left of t, and E be the set containing all tokens in S that
start in the same column as t.
• The constraint is that t must be indented further than every token in L, and aligned with every token in E.
Note that if any token in L or E belongs to a previous code block, then the constraint may not be satisfied un-
less (say) the AgdaAlign environment is used in an appropriate way. If custom settings are used, for instance if
\AgdaIndent is redefined, then the constraint discussed above may not be satisfied.
Examples:
• Here C is indented further than B:

postulate
A B
C : Set

• Here C is not (necessarily) indented further than B, because X shadows B:

postulate
A B : Set
X
C : Set

212 Chapter 4. Tools


Agda User Manual, Release 2.6.2

These rules are inspired by, but not identical to, the one used by lhs2TeX’s poly mode (see Section 8.4 of the manual
for lhs2TeX version 1.17).

Counting Extended Grapheme Clusters

The alignment feature regards the string + , containing + and a combining character, as having length two. However,
it seems more reasonable to treat it as having length one, as it occupies a single column, if displayed “properly” using
a monospace font. The flag --count-clusters is an attempt at fixing this. When this flag is enabled the backend
counts “extended grapheme clusters” rather than code points.
Note that this fix is not perfect: a single extended grapheme cluster might be displayed in different ways by different
programs, and might, in some cases, occupy more than one column. Here are some examples of extended grapheme
clusters, all of which are treated as a single character by the alignment algorithm:

+
O¨^
PDF TODOPDF TODO
PDF TODOPDF TODOPDF TODO
PDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TODOPDF TO

Note also that the layout machinery does not count extended grapheme clusters, but code points. The following code
is syntactically correct, but if --count-clusters is used, then the LaTeX backend does not align the two field
keywords:

record + : Set1 where field A : Set


field B : Set

The --count-clusters flag is not enabled in all builds of Agda, because the implementation depends on the ICU
library, the installation of which could cause extra trouble for some users. The presence of this flag is controlled by
the Cabal flag enable-cluster-counting.

Breaking up code blocks

Sometimes one might want to break up a code block into multiple pieces, but keep code in different blocks aligned
with respect to each other. Then one can use the AgdaAlign environment. Example usage:

\begin{AgdaAlign}
\begin{code}
code
code (more code)
\end{code}
Explanation...
\begin{code}
aligned with "code"
code (aligned with (more code))
\end{code}
\end{AgdaAlign}

Note that AgdaAlign environments should not be nested.


Sometimes one might also want to hide code in the middle of a code block. This can be accomplished in the following
way:

4.7. Generating LaTeX 213


Agda User Manual, Release 2.6.2

\begin{AgdaAlign}
\begin{code}
visible
\end{code}
\begin{code}[hide]
hidden
\end{code}
\begin{code}
visible
\end{code}
\end{AgdaAlign}

However, the result may be ugly: extra space is perhaps inserted around the code blocks. The AgdaSuppressSpace
environment ensures that extra space is only inserted before the first code block, and after the last one (but not if
\AgdaNoSpaceAroundCode{} is used). Example usage:

\begin{AgdaAlign}
\begin{code}
code
more code
\end{code}
Explanation...
\begin{AgdaSuppressSpace}
\begin{code}
aligned with "code"
aligned with "more code"
\end{code}
\begin{code}[hide]
hidden code
\end{code}
\begin{code}
also aligned with "more code"
\end{code}
\end{AgdaSuppressSpace}
\end{AgdaAlign}

Note that AgdaSuppressSpace environments should not be nested. There is also a combined environment,
AgdaMultiCode, that combines the effects of AgdaAlign and AgdaSuppressSpace.

Hiding code

Code that you do not want to show up in the output can be hidden by giving the argument hide to the code block:

\begin{code}[hide]
-- the code here will not be part of the final document
\end{code}

Hyperlinks (experimental)

If the hyperref latex package is loaded before the agda package and the links option is passed to the agda package,
then the agda package provides a function called \AgdaTarget. Identifiers which have been declared targets, by the
user, will become clickable hyperlinks in the rest of the document. Here is a small example:

214 Chapter 4. Tools


Agda User Manual, Release 2.6.2

\documentclass{article}
\usepackage{hyperref}
\usepackage[links]{agda}
\begin{document}

\AgdaTarget{ } N
\AgdaTarget{zero}
\begin{code}
data N: Set where
zero : N
suc : N→ N
\end{code}

See next page for how to define \AgdaFunction{two} (doesn't turn into a
link because the target hasn't been defined yet). We could do it
manually though; \hyperlink{two}{\AgdaDatatype{two}}.

\newpage

\AgdaTarget{two}
\hypertarget{two}{}
\begin{code}
two : N
two = suc (suc zero)
\end{code}

\AgdaInductiveConstructor{zero} is of type
N
\AgdaDatatype{ }. \AgdaInductiveConstructor{suc} has not been defined to
be a target so it doesn't turn into a link.

\newpage

Now that the target for \AgdaFunction{two} has been defined the link
works automatically.

\begin{code}
data Bool : Set where
true false : Bool
\end{code}

The AgdaTarget command takes a list as input, enabling several targets


to be specified as follows:

\AgdaTarget{if, then, else, if\_then\_else\_}


\begin{code}
if_then_else_ : {A : Set} → Bool → A → A → A
if true then t else f = t
if false then t else f = f
\end{code}

\newpage

Mixfix identifier need their underscores escaped:


\AgdaFunction{if\_then\_else\_}.

\end{document}

The borders around the links can be suppressed using hyperref’s hidelinks option:

4.7. Generating LaTeX 215


Agda User Manual, Release 2.6.2

\usepackage[hidelinks]{hyperref}

Warning: The current approach to links does not keep track of scoping or types, and hence overloaded names
might create links which point to the wrong place. Therefore it is recommended to not overload names when using
the links option at the moment. This might get fixed in the future.

Numbered code listings

When the option number is used an equation number is generated for the code listing. The number is set to
the right, centered vertically. By default the number is set in parentheses, but this can be changed by redefining
\AgdaFormatCodeNumber.
The option can optionally be given an argument: when number=l is used a label l, referring to the code listing, is
generated. It is possible to use this option several times with different labels.
An example:

\begin{code}[number=code:lemma]
a proof
\end{code}
%
A consequence of Lemma~\ref{code:lemma} is that...

The option number has no effect if used together with hide, inline or inline*.

Inline code

Code can be typeset inline by giving the argument inline to the code block:

Assume that we are given a type


%
\begin{code}[hide]
module _ (
\end{code}
\begin{code}[inline]
A : Set
\end{code}
\begin{code}[hide]
) where
\end{code}
%
.

There is also a variant of inline, inline*. If inline* is used, then space (\AgdaSpace{}) is added at the
end of the code, and when inline is used space is not added.
The implementation of these options is a bit of a hack. Only use these options for typesetting a single line of code
without multiple consecutive whitespace characters (except at the beginning of the line).

Another way to typeset inline code

An alternative to using inline and inline* is to typeset code manually. Here is an example:

216 Chapter 4. Tools


Agda User Manual, Release 2.6.2

Below we postulate the existence of a type called


\AgdaPostulate{apa}:
%
\begin{code}
postulate apa : Set
\end{code}

You can find all the commands used by the backend (and which you can use manually) in the agda.sty file.

Semi-automatically typesetting inline code (experimental)

Since Agda version 2.4.2 there is experimental support for semi-automatically typesetting code inside text, using the
references option. After loading the agda package with this option, inline Agda snippets will be typeset in the
same way as code blocks—after post-processing—if referenced using the \AgdaRef command. Only the current
module is used; should you need to reference identifiers in other modules, then you need to specify which other
module manually by using \AgdaRef[module]{identifier}.
In order for the snippets to be typeset correctly, they need to be post-processed by the postprocess-latex.pl
script from the Agda data directory. You can copy it into the current directory by issuing the command

$ cp $(dirname $(dirname $(agda-mode locate)))/postprocess-latex.pl .

In order to generate a PDF, you can then do the following:

$ agda --latex {file}.lagda


$ cd latex/
$ perl ../postprocess-latex.pl {file}.tex > {file}.processed
$ mv {file}.processed {file}.tex
$ xelatex {file}.tex

Here is a full example, consisting of a Literate Agda file Example.lagda and a makefile Makefile.

Listing 1: Example.lagda
\documentclass{article}
\usepackage[references]{agda}

\begin{document}

Here we postulate \AgdaRef{apa}.


%
\begin{code}
postulate apa : Set
\end{code}

\end{document}

Listing 2: Makefile
AGDA=agda
AFLAGS=-i. --latex
SOURCE=Example
POSTPROCESS=postprocess-latex.pl
LATEX=latexmk -pdf -use-make -xelatex

(continues on next page)

4.7. Generating LaTeX 217


Agda User Manual, Release 2.6.2

(continued from previous page)


all:
$(AGDA) $(AFLAGS) $(SOURCE).lagda
cd latex/ && \
perl ../$(POSTPROCESS) $(SOURCE).tex > $(SOURCE).processed && \
mv $(SOURCE).processed $(SOURCE).tex && \
$(LATEX) $(SOURCE).tex && \
mv $(SOURCE).pdf ..

See Issue #1054 on the bug tracker for implementation details.

Warning: Overloading identifiers should be avoided. If multiple identifiers with the same name exist, then
AgdaRef will typeset according to the first one it finds.

Controlling the typesetting of individual tokens

The typesetting of (certain) individual tokens can be controlled by redefining the \AgdaFormat command. Example:

\usepackage{ifthen}

% Insert extra space before some tokens.


\DeclareRobustCommand{\AgdaFormat}[2]{%
\ifthenelse{
\equal{#1}{≡⟨} \OR
\equal{#1}{≡⟨⟩} \OR
\equal{#1}{}
}{\ }{}#2}

Note the use of \DeclareRobustCommand. The first argument to \AgdaFormat is the token, and the second
argument the thing to be typeset.

Emulating %format rules

The LaTeX backend has no feature directly comparable to lhs2TeX’s %format rules. However, one can hack up
something similar by using a program like sed. For instance, let us say that replace.sed contains the following
text:

# Turn Σ[ x ∈ X ] into (x : X) ×.
s/\\AgdaRecord{Σ\[} \(.*\) \\AgdaRecord{∈} \(.*\) \\AgdaRecord{]}/\\AgdaSymbol\{(\}\1
˓→\\AgdaSymbol\{:\} \2\\AgdaSymbol\{)\} \\AgdaFunction\{×\}/g

The output of the LaTeX backend can then be postprocessed in the following way:

$ sed -f replace.sed {file}.tex > {file}.sedded


$ mv {file}.sedded {file}.tex

Including Agda code in a larger LaTeX document

Sometimes you might want to include a bit of code without making the whole document a literate Agda file. Here is
one way in which this can be accomplished. (Perhaps this technique was invented by Anton Setzer.) Put the code in a
separate file, and use \newcommand to give a name to each piece of code that should be typeset:

218 Chapter 4. Tools


Agda User Manual, Release 2.6.2

Listing 3: Code.lagda.tex
\newcommand{\nat}{%
\begin{code}
data N: Set where
zero : N
suc : (n : ) → N N
\end{code}}

Preprocess this file using Agda, and then include it in another file in the following way:

Listing 4: Main.tex
% In the preamble:
\usepackage{agda}
% Further setup related to Agda code.

% The Agda code can be included either in the preamble or in the


% document's body.
\input{Code}

% Then one can refer to the Agda code in the body of the text:
The natural numbers can be defined in the following way in Agda:
\nat{}

Here it is assumed that agda.sty is available in the current directory (or on the TeX search path).
Note that this technique can also be used to present code in a different order, if the rules imposed by Agda are not
compatible with the order that you would prefer.

4.7.5 Examples

Some examples that can be used for inspiration (in the HTML version of the manual you see links to the source code
and in the PDF version of the manual you see inline source code).
• For the article class and pdfLaTeX:

\documentclass{article}

% Use the input encoding UTF-8 and the font encoding T1.
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

% Support for Agda code.


\usepackage{agda}

% Customised setup for certain characters.


\usepackage{newunicodechar}
\newunicodechar{∀}{\ensuremath{\mathnormal{\forall}}}
\newunicodechar{→}{\ensuremath{\mathnormal{\to}}}
\newunicodechar{1 }{\ensuremath{{}_1}}

% Support for Greek letters.


\usepackage{alphabeta}

% Disable ligatures that start with '-'. Note that this affects the
(continues on next page)

4.7. Generating LaTeX 219


Agda User Manual, Release 2.6.2

(continued from previous page)


% entire document!
\usepackage{microtype}
\DisableLigatures[-]{encoding=T1}

\begin{document}

Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

Θ1 : Set → Set
Θ1 = 𝜆 A → A

a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.

\end{document}

• For the article class and LuaLaTeX or XeLaTeX:


– If you want to use the default fonts (with—at the time of writing—bad coverage of non-ASCII characters):

\documentclass{article}

% Support for Agda code.


\usepackage{agda}

% Use special font families without TeX ligatures for Agda code. (This
% code is inspired by a comment by Enrico Gregorio/egreg:
% https://tex.stackexchange.com/a/103078.)
\usepackage{fontspec}
\newfontfamily{\AgdaSerifFont}{Latin Modern Roman}
\newfontfamily{\AgdaSansSerifFont}{Latin Modern Sans}
\newfontfamily{\AgdaTypewriterFont}{Latin Modern Mono}
\renewcommand{\AgdaFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaKeywordFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaStringFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaCommentFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaBoundFontStyle}[1]{\textit{\AgdaSerifFont{}#1}}

% Workarounds for the fact that the Latin Modern Sans font does not
% support certain characters. An alternative would be to use another
% font.
\usepackage{newunicodechar}
\newunicodechar{𝜆}{\ensuremath{\mathnormal{\lambda}}}
\newunicodechar{∀}{\ensuremath{\mathnormal{\forall}}}
\newunicodechar{1 }{\ensuremath{{}_1}}
(continues on next page)

220 Chapter 4. Tools


Agda User Manual, Release 2.6.2

(continued from previous page)

\begin{document}

Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

Θ1 : Set → Set
Θ1 = 𝜆 A → A

a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.

\end{document}

– If you would prefer to use other fonts (with possibly better coverage):
\documentclass{article}

% Support for Agda code.


\usepackage{agda}

% Use fonts with a decent coverage of non-ASCII characters.


\usepackage{fontspec}
\setmainfont{DejaVu Serif}
\setsansfont{DejaVu Sans}
\setmonofont{DejaVu Sans Mono}

% Use special font families without TeX ligatures for Agda code. (This
% code is inspired by a comment by Enrico Gregorio/egreg:
% https://tex.stackexchange.com/a/103078.)
\newfontfamily{\AgdaSerifFont}{DejaVu Serif}
\newfontfamily{\AgdaSansSerifFont}{DejaVu Sans}
\newfontfamily{\AgdaTypewriterFont}{DejaVu Sans Mono}
\renewcommand{\AgdaFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaKeywordFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaStringFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaCommentFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaBoundFontStyle}[1]{\textit{\AgdaSerifFont{}#1}}

\begin{document}

Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String


(continues on next page)

4.7. Generating LaTeX 221


Agda User Manual, Release 2.6.2

(continued from previous page)

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

Θ1 : Set → Set
Θ1 = 𝜆 A → A

a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.

\end{document}

• For the beamer class and pdfLaTeX:


\documentclass{beamer}

% Use the input encoding UTF-8 and the font encoding T1.
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}

% Support for Agda code.


\usepackage{agda}

% Decrease the indentation of code.


\setlength{\mathindent}{1em}

% Customised setup for certain characters.


\usepackage{newunicodechar}
\newunicodechar{∀}{\ensuremath{\mathnormal{\forall}}}
\newunicodechar{→}{\ensuremath{\mathnormal{\to}}}
\newunicodechar{1 }{\ensuremath{{}_1}}

% Support for Greek letters.


\usepackage{alphabeta}

% Disable ligatures that start with '-'. Note that this affects the
% entire document!
\usepackage{microtype}
\DisableLigatures[-]{encoding=T1}

\begin{document}

\begin{frame}
Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

(continues on next page)

222 Chapter 4. Tools


Agda User Manual, Release 2.6.2

(continued from previous page)


Θ1 : Set → Set
Θ1 = 𝜆 A → A

a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.
\end{frame}

\end{document}

• For the beamer class and LuaLaTeX or XeLaTeX:


\documentclass{beamer}

% Support for Agda code.


\usepackage{agda}

% Decrease the indentation of code.


\setlength{\mathindent}{1em}

% Use special font families without TeX ligatures for Agda code. (This
% code is inspired by a comment by Enrico Gregorio/egreg:
% https://tex.stackexchange.com/a/103078.)
\usepackage{fontspec}
\newfontfamily{\AgdaSerifFont}{Latin Modern Roman}
\newfontfamily{\AgdaSansSerifFont}{Latin Modern Sans}
\newfontfamily{\AgdaTypewriterFont}{Latin Modern Mono}
\renewcommand{\AgdaFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaKeywordFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaStringFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaCommentFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaBoundFontStyle}[1]{\textit{\AgdaSansSerifFont{}#1}}

% Workarounds for the fact that the Latin Modern Sans font does not
% support certain characters.
\usepackage{newunicodechar}
\newunicodechar{𝜆}{\ensuremath{\mathnormal{\lambda}}}
\newunicodechar{∀}{\ensuremath{\mathnormal{\forall}}}
\newunicodechar{1 }{\ensuremath{{}_1}}

\begin{document}

\begin{frame}
Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

Θ1 : Set → Set
(continues on next page)

4.7. Generating LaTeX 223


Agda User Manual, Release 2.6.2

(continued from previous page)


Θ1 = 𝜆 A → A

a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.
\end{frame}

\end{document}

• For the acmart class and pdfLaTeX:


\documentclass[acmsmall]{acmart}

% Use the UTF-8 encoding.


\usepackage[utf8]{inputenc}

% Support for Agda code.


\usepackage{agda}

% Code should be indented.


\setlength{\mathindent}{1em}

% Customised setup for certain characters.


\usepackage{newunicodechar}
\newunicodechar{∀}{\ensuremath{\mathnormal{\forall}}}
\newunicodechar{1 }{\ensuremath{{}_{\textsf{1}}}}

% Support for Greek letters.


\usepackage{alphabeta}

% Disable ligatures that start with '-'. Note that this affects the
% entire document! Note also that if all you want to do is to ensure
% that the comment starter '--' is typeset with two characters, then
% you do not need this command, because '--' is not typeset as an en
% dash (-) when the typewriter font is used.
\DisableLigatures[-]{encoding=T1}

\begin{document}
\acmConference{Some conference}
\maketile

Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

Θ1 : Set → Set
Θ1 = 𝜆 A → A

(continues on next page)

224 Chapter 4. Tools


Agda User Manual, Release 2.6.2

(continued from previous page)


a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.

\end{document}

• For the acmart class and XeLaTeX:


\documentclass[acmsmall]{acmart}

% Support for Agda code.


\usepackage{agda}

% Code should be indented.


\setlength{\mathindent}{1em}

% Use special font families without TeX ligatures for Agda code. (This
% code is inspired by a comment by Enrico Gregorio/egreg:
% https://tex.stackexchange.com/a/103078.)
\usepackage{fontspec}
\newfontfamily{\AgdaSerifFont}{Linux Libertine O}
\newfontfamily{\AgdaSansSerifFont}{Linux Biolinum O}
\newfontfamily{\AgdaTypewriterFont}{inconsolata}
\renewcommand{\AgdaFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaKeywordFontStyle}[1]{{\AgdaSansSerifFont{}#1}}
\renewcommand{\AgdaStringFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaCommentFontStyle}[1]{{\AgdaTypewriterFont{}#1}}
\renewcommand{\AgdaBoundFontStyle}[1]{\textit{\AgdaSerifFont{}#1}}

\begin{document}
\acmConference{Some conference}
\maketile

Some code:
\begin{code}
{-# OPTIONS --without-K --count-clusters #-}

open import Agda.Builtin.String

-- A comment with some TeX ligatures:


-- --, ---, ?`, !`, `, ``, ', '', <<, >>.

Θ1 : Set → Set
Θ1 = 𝜆 A → A

a-name-with--hyphens : ∀ {A : Set} → A → A
a-name-with--hyphens ff--fl = ff--fl

ffi : String
ffi = "--"
\end{code}
Note that the code is indented.

(continues on next page)

4.7. Generating LaTeX 225


Agda User Manual, Release 2.6.2

(continued from previous page)


\end{document}

Note that these examples might not satisfy all your requirements, and might not work in all settings (in particular, for
LuaLaTeX or XeLaTeX it might be necessary to install one or more fonts). If you have to follow a particular house
style, then you may want to make sure that the Agda code follows this style, and that you do not inadvertently change
the style of other text when customising the style of the Agda code.

4.8 Interface files

Note: This is a stub. Contributions, additions and corrections are greatly appreciated.

When an .agda file is saved, another file with the same name and extension .agdai is automatically created. The
latter file is what we call an interface file.
Interface files store the results from the type-checking process. These results include:
• A translation of pattern-matching definitions to case trees (this translation speeds up computation).
• The resolution of all implicit arguments. (Note: under the flag --allow-unsolved-metas not all implicit
arguments need to be resolved to create an interface file.)

4.8.1 Storage

In projects that do not use any Agda library, the .agdai files are stored alongside the .agda source file.
If the .agda source file is part of a project with an identifiable root (i.e. if there is an .agda-lib file in any of the
directories above it), then the interface file is stored in the _build/VERSION directory at the identified root. This
prevents losing the interface file when switching between agda versions. You can revert this behaviour with the flag
--no-project.

Note: When an .agda file is renamed, the old .agdai file is kept, and a new .agdai file is created. This is the
intended behavior, and the orphan files can be safely deleted from the user’s file system if needed.

The compression run to create .agdai files introduces sharing. Sharing improves the memory efficiency of the code
loaded from interface files.
The syntax represented in .agdai files differs significantly from the syntax of source files.

4.8.2 Compilation

An external module is loaded by loading its interface file. Interface files are also intermediate points when compiling
through a backend to e.g. Haskell.

4.9 Library Management

Agda has a simple package management system to support working with multiple libraries in different locations. The
central concept is that of a library.

226 Chapter 4. Tools


Agda User Manual, Release 2.6.2

4.9.1 Example: Using the standard library

Before we go into details, here is some quick information for the impatient on how to tell Agda about the location of
the standard library, using the library management system.
Let’s assume you have downloaded the standard library into a directory which we will refer to by AGDA_STDLIB (as
an absolute path). A library file standard-library.agda-lib should exist in this directory, with the following
content:

name: standard-library
include: src

To use the standard library by default in your Agda projects, you have to do two things:
1. Create a file AGDA_DIR/libraries with the following content:

AGDA_STDLIB/standard-library.agda-lib

(Of course, replace AGDA_STDLIB by the actual path.)


The AGDA_DIR defaults to ~/.agda on unix-like systems and C:\Users\USERNAME\AppData\Roaming\agda
or similar on Windows. (More on AGDA_DIR below.)
Remark: The libraries file informs Agda about the libraries you want it to know about.

2. Create a file AGDA_DIR/defaults with the following content:

standard-library

Remark: The defaults file informs Agda which of the libraries pointed to by libraries should be used
by default (i.e. in the default include path).
That’s the short version, if you want to know more, read on!

4.9.2 Library files

A library consists of
• a name
• a set of dependencies
• a set of include paths
• a set of default flags
Libraries are defined in .agda-lib files with the following syntax:

name: LIBRARY-NAME -- Comment


depend: LIB1 LIB2
LIB3
LIB4
include: PATH1
PATH2
PATH3
(continues on next page)

4.9. Library Management 227


Agda User Manual, Release 2.6.2

(continued from previous page)


flags: OPTION1 OPTION2
OPTION3

Dependencies are library names, not paths to .agda-lib files, and include paths are relative to the location of the
library-file.
Default flags can be any valid pragma options (see Command-line and pragma options).
Each of the four fields is optional. Naturally, unnamed libraries cannot be depended upon. But dropping the name is
possible if the library file only serves to list include paths and/or dependencies of the current project.

4.9.3 Installing libraries

To be found by Agda a library file has to be listed (with its full path) in a libraries file
• AGDA_DIR/libraries-VERSION, or if that doesn’t exist
• AGDA_DIR/libraries
where VERSION is the Agda version (for instance 2.5.1). The AGDA_DIR defaults to ~/.agda on unix-like
systems and C:\Users\USERNAME\AppData\Roaming\agda or similar on Windows, and can be overridden
by setting the AGDA_DIR environment variable.
Each line of the libraries file shall be the absolute file system path to the root of a library.
Environment variables in the paths (of the form $VAR or ${VAR}) are expanded. The location of the libraries
file used can be overridden using the --library-file=FILE command line option.
You can find out the precise location of the libraries file by calling agda -l fjdsk Dummy.agda at the
command line and looking at the error message (assuming you don’t have a library called fjdsk installed).
Note that if you want to install a library so that it is used by default, it must also be listed in the defaults file (details
below).

4.9.4 Using a library

There are three ways a library gets used:


• You supply the --library=LIB (or -l LIB) option to Agda. This is equivalent to adding a -iPATH for
each of the include paths of LIB and its (transitive) dependencies.
• No explicit --library flag is given, and the current project root (of the Agda file that is being loaded) or
one of its parent directories contains an .agda-lib file defining a library LIB. This library is used as if
a --library=LIB option had been given, except that it is not necessary for the library to be listed in the
AGDA_DIR/libraries file.
• No explicit --library flag, and no .agda-lib file in the project root. In this case the file AGDA_DIR/
defaults is read and all libraries listed are added to the path. The defaults file should contain a list of
library names, each on a separate line. In this case the current directory is also added to the path.
To disable default libraries, you can give the flag --no-default-libraries. To disable using libraries
altogether, use the --no-libraries flag.

4.9.5 Default libraries

If you want to usually use a variety of libraries, it is simplest to list them all in the AGDA_DIR/defaults file.

228 Chapter 4. Tools


Agda User Manual, Release 2.6.2

Each line of the defaults file shall be the name of a library resolvable using the paths listed in the libraries file. For
example,

standard-library
library2
library3

where of course library2 and library3 are the libraries you commonly use. While it is safe to list all your
libraries in library, be aware that listing libraries with name clashes in defaults can lead to difficulties, and
should be done with care (i.e. avoid it unless you really must).

4.9.6 Version numbers

Library names can end with a version number (for instance, mylib-1.2.3). When resolving a library name (given
in a --library flag, or listed as a default library or library dependency) the following rules are followed:
• If you don’t give a version number, any version will do.
• If you give a version number an exact match is required.
• When there are multiple matches an exact match is preferred, and otherwise the latest matching version is
chosen.
For example, suppose you have the following libraries installed: mylib, mylib-1.0, otherlib-2.1, and
otherlib-2.3. In this case, aside from the exact matches you can also say --library=otherlib to get
otherlib-2.3.

4.9.7 Upgrading

If you are upgrading from a pre 2.5 version of Agda, be aware that you may have remnants of the previous library
management system in your preferences. In particular, if you get warnings about agda2-include-dirs, you will
need to find where this is defined. This may be buried deep in .el files, whose location is both operating system and
emacs version dependant.

4.10 Performance debugging

Sometimes your Agda program doesn’t type check or run as fast as you expected. This section describes some tools
available to figure out why not.

Note: This is a stub

4.10.1 Measuring typechecking performance

Agda can do some internal book-keeping of how time is spent, which can be turned on using the profile verbosity:

-vprofile.definitions:10
Break down by time spent checking each top-level definition.
-vprofile.modules:10
Break down by time spent checking each top-level module.

4.10. Performance debugging 229


Agda User Manual, Release 2.6.2

-vprofile:7
Break down by activity (such as parsing, type checking, termination checking, etc).
The Haskell runtime system can also tell you something about how Agda spends its time:
+RTS -s -RTS
Show memory usage and time spent on garbage collection.

External tools

• agda-bench is a tool for benchmarking compile-time evaluation and type checking performance of Agda pro-
grams.

4.10.2 Measuring run-time performance

Agda programs are compiled (by default) via Haskell (see Compilers), so the GHC profiling tools can be applied to
Agda programs. For instance,

> agda -c Test.agda --ghc-flag=-prof --ghc-flag=-fprof-auto


> ./Test +RTS -p

A complication is that the GHC backend generates names like d76, so making sense of the profiling output can require
a little bit of work.

External tools

• agda-criterion has bindings for a small part of the criterion Haskell library for performance measurement.
• agda-ghc-names can translate the names in generated Haskell code back to Agda names.

4.11 Search Definitions in Scope

Since version 2.5.1 Agda supports the command Search About that searches the objects in scope, looking for
definitions matching a set of constraints given by the user.

4.11.1 Usage

The tool is invoked by choosing Search About in the goal menu or pressing C-c C-z. It opens a prompt and
users can then input a list of space-separated identifiers and string literals. The search returns the definitions in scope
whose type contains all of the mentioned identifiers and whose name contains all of the string literals as substrings.
For instance, in the following module:

open import Agda.Builtin.Char


open import Agda.Builtin.Char.Properties
open import Agda.Builtin.String
open import Agda.Builtin.String.Properties

running Search About on Char String returns:


Definitions about Char, String
primShowChar : Char → String

230 Chapter 4. Tools


Agda User Manual, Release 2.6.2

primStringFromList : Agda.Builtin.List.List Char → String


primStringToList : String → Agda.Builtin.List.List Char
primStringToListInjective
: (a b [String) →] primStringToList a Agda.Builtin.Equality.≡ primStringToList b → a
Agda.Builtin.Equality.≡ b
and running Search About on String "Injective" returns:
Definitions about String, “Injective”
primStringToListInjective
: (a b [String) →] primStringToList a Agda.Builtin.Equality.≡ primStringToList b → a
Agda.Builtin.Equality.≡ b

4.11. Search Definitions in Scope 231


Agda User Manual, Release 2.6.2

232 Chapter 4. Tools


CHAPTER 5

Contribute

Agda and its related libraries are hosted at Github. To contribute, you will need to fork a repository, make the changes
and then send a pull request (PR).
A code of conduct and other considerations are described in the HACKING.md file in the root of the Agda repository.
You can also take a look at the current Agda issues to help us solve them. You can start with the label difficulty: easy
and help wanted. You can also explore all the labels.

Note: The Agda User Manual is a work-in-progress and is still incomplete. Contributions, additions, and corrections
to the Agda manual are greatly appreciated.

5.1 Documentation

Documentation is written in reStructuredText format.


The Agda documentation is shipped together with the main Agda repository in the doc/user-manual subdirectory.
The content of this directory is automatically published to https://agda.readthedocs.io.

5.1.1 Rendering documentation locally

• To build the user manual locally, you need to install the following dependencies:
– Python ≥3.3
– Sphinx and sphinx-rtd-theme

pip install --user -r doc/user-manual/requirements.txt

Note that the --user option puts the Sphinx binaries in $HOME/.local/bin.
– ImageMagick with SVG and PNG support; check output of

233
Agda User Manual, Release 2.6.2

convert -list format

– LaTeX
– PyDvi
To see the list of available targets, execute make help in doc/user-manual. E.g., call make html to
build the documentation in html format.

5.1.2 Type-checking code examples

You can include code examples in your documentation.


If your give the documentation file the extension .lagda.rst, Agda will recognise it as an Agda file and type-check
it.

Tip: If you edit .lagda.rst documentation files in Emacs, you can use Agda’s interactive mode to write your
code examples. Run M-x agda2-mode to switch to Agda mode, and M-x rst-mode to switch back to rST mode.

You can check that all the examples in the manual are type-correct by running make user-manual-test from
the root directory. This check will be run as part of the continuous integration build.

Warning: Remember to run fix-agda-whitespace to remove trailing whitespace before submitting the
documentation to the repository.

5.1.3 Syntax for code examples

The syntax for embedding code examples depends on:


1. Whether the code example should be visible to the reader of the documentation.
2. Whether the code example contains valid Agda code (which should be type-checked).

Visible, checked code examples

This is code that the user will see, and that will be also checked for correctness by Agda. Ideally, all code in the
documentation should be of this form: both visible and valid.

It can appear stand-alone:

::

data Bool : Set where


true false : Bool

Or at the end of a paragraph::

data Bool : Set where


true false : Bool

Here ends the code fragment.

234 Chapter 5. Contribute


Agda User Manual, Release 2.6.2

Result:
It can appear stand-alone:

data Bool : Set where


true false : Bool

Or at the end of a paragraph:

data Bool : Set where


true false : Bool

Here ends the code fragment.

Warning: Remember to always leave a blank like after the ::. Otherwise, the code will be checked by Agda, but
it will appear as regular paragraph text in the documentation.

Visible, unchecked code examples

This is code that the reader will see, but will not be checked by Agda. It is useful for examples of incorrect code,
program output, or code in languages different from Agda.

.. code-block:: agda

-- This is not a valid definition

𝜔 : ∀ a → a
𝜔 x = x

.. code-block:: haskell

-- This is haskell code

data Bool = True | False

Result:

-- This is not a valid definition

𝜔 : ∀ a → a
𝜔 x = x

-- This is haskell code

data Bool = True | False

Invisible, checked code examples

This is code that is not shown to the reader, but which is used to typecheck the code that is actually displayed.
This might be definitions that are well known enough that do not need to be shown again.

5.1. Documentation 235


Agda User Manual, Release 2.6.2

..
::
data Nat : Set where
zero : Nat
suc : Nat → Nat

::

add : Nat → Nat → Nat


add zero y = y
add (suc x) y = suc (add x y)

Result:

add : Nat → Nat → Nat


add zero y = y
add (suc x) y = suc (add x y)

File structure

Documentation literate files (.lagda.*) are type-checked as whole Agda files, as if all literate text was replaced by
whitespace. Thus, indentation is interpreted globally.

Namespacing

In the documentation, files are typechecked starting from the doc/user-manual/ root. For example, the file doc/user-
manual/language/data-types.lagda.rst should start with a hidden code block declaring the name of the module as
language.data-types:

..
::
module language.data-types where

Scoping

Sometimes you will want to use the same name in different places in the same documentation file. You can do this by
using hidden module declarations to isolate the definitions from the rest of the file.

..
::
module scoped-1 where

::

foo : Nat
foo = 42

..
::
module scoped-2 where

::
(continues on next page)

236 Chapter 5. Contribute


Agda User Manual, Release 2.6.2

(continued from previous page)


foo : Nat
foo = 66

Result:

foo : Nat
foo = 42

5.1. Documentation 237


Agda User Manual, Release 2.6.2

238 Chapter 5. Contribute


CHAPTER 6

The Agda Team and License

Agda 2 was originally written by Ulf Norell, partially based on code from Agda 1 by Catarina Coquand and Makoto
Takeyama, and from Agdalight by Ulf Norell and Andreas Abel.
Agda 2 is currently actively developed mainly by (in alphabetical order):
• Andreas Abel
• Guillaume Allais
• Liang-Ting Chen
• Jesper Cockx
• Nils Anders Danielsson
• Víctor López Juan
• Ulf Norell
• Andrés Sicard-Ramírez
• Andrea Vezzosi
• Tesla Ice Zhang
Agda 2 has received major contributions by the following developers, amongst others. Some contributors have pi-
oneered a feature which shall be mentioned here. But many have worked on these features for improvements and
maintenance.
• Andreas Abel: termination checker, sized types, irrelevance, copatterns
• Guillaume Allais: warnings, pattern guards, standard library 1.0
• Stevan Andjelkovic: LaTeX backend
• Miëtek Bak: Agda logo
• Marcin Benke: original “Alonzo” compiler to Haskell
• Jean-Philippe Bernardy: syntax declarations
• Guillaume Brunerie

239
Agda User Manual, Release 2.6.2

• James Chapman
• Liang-Ting Chen: github workflows
• Jesper Cockx: rewriting, unification --without-K
• Catarina Coquand: Agda 1
• Matthew Daggitt: standard library 1.0
• Nils Anders Danielsson: efficient positivity checker, HTML backend, highlighting, standard library
• Dominique Devriese: instance arguments
• Péter Diviánszky: web frontent, variable declarations
• Robert Estelle
• Olle Fredriksson: Epic compiler backend
• Paolo Giarrusso
• Adam Gundry: pattern synonyms
• Daniel Gustafsson: Epic compiler backend
• Philipp Hausmann: treeless compiler, UHC compiler backend, testsuite runner, Travis CI
• Kuen-Bang Hou “favonia”
• Patrik Jansson
• Alan Jeffrey: JavaScript compiler backend
• Wolfram Kahl
• Wen Kokke
• John Leo
• Fredrik Lindblad: Agsy proof search “Auto”
• Víctor López Juan: “tog” prototype, markdown frontend, documentation*
• Ting-Gan Lua
• Francesco Mazzoli: “tog” prototype*
• Stefan Monnier
• Guilhem Moulin: highlighting
• Fredrik Nordvall Forsberg: pattern lambdas, warnings
• Ulf Norell: Agda 2
• Nicolas Pouillard: module record expressions
• Benjamin Price
• Jonathan Prieto: Agda package manager
• Nobuo Yamashita
• Christian Sattler
• Andrés Sicard-Ramírez: Agda releases, Travis CI
• Makoto Takeyama: Agda 1, Emacs mode, “MAlonzo” compiler to Haskell, serialization
• Andrea Vezzosi: Cubical Agda, Agda-flat, Agda-parametric

240 Chapter 6. The Agda Team and License


Agda User Manual, Release 2.6.2

• Noam Zeilberger: pattern lambdas


• Tesla Ice Zhang
The full list of contributors (more than 140) is available at https://github.com/agda/agda/graphs/contributors .
The Agda license is here.

241
Agda User Manual, Release 2.6.2

242 Chapter 6. The Agda Team and License


CHAPTER 7

Indices and tables

• genindex
• search

243
Agda User Manual, Release 2.6.2

244 Chapter 7. Indices and tables


Bibliography

[McBride2004] C. McBride and J. McKinna. The view from the left. Journal of Functional Programming, 2004.
http://strictlypositive.org/vfl.pdf.

245
Agda User Manual, Release 2.6.2

246 Bibliography
Index

Symbols command line option, 192


+RTS -s -RTS -help[={TOPIC}], -?[{TOPIC}]
command line option, 230 command line option, 188
-allow-exec -html
command line option, 191 command line option, 189
-allow-incomplete-matches -html-dir={DIR}
command line option, 191 command line option, 189
-allow-unsolved-metas -html-highlight=[code,all,auto]
command line option, 191 command line option, 189
-auto-inline -ignore-all-interfaces
command line option, 192 command line option, 189
-caching, -no-caching -ignore-interfaces
command line option, 190 command line option, 189
-call-by-name -include-path={DIR}, -i={DIR}
command line option, 192 command line option, 189
-compile-dir={DIR} -injective-type-constructors
command line option, 189 command line option, 191
-confluence-check, -instance-search-depth={N}
-local-confluence-check command line option, 192
command line option, 190 -interaction
-copatterns, -no-copatterns command line option, 188
command line option, 190 -interaction-json
-count-clusters command line option, 188
command line option, 189 -interactive, -I
-css={URL} command line option, 188
command line option, 189 -inversion-max-depth={N}
-cubical command line option, 192
command line option, 190 -irrelevant-projections,
-cumulativity, -no-cumulativity -no-irrelevant-projections
command line option, 193 command line option, 192
-dependency-graph={FILE} -keep-pattern-variables
command line option, 189 command line option, 191
-double-check -latex
command line option, 192 command line option, 189
-exact-split, -no-exact-split -latex-dir={DIR}
command line option, 191 command line option, 189
-experimental-irrelevance -library-file={FILE}
command line option, 191 command line option, 189
-guardedness, -no-guardedness -library={DIR}, -l={LIB}
command line option, 189

247
Agda User Manual, Release 2.6.2

-local-interfaces command line option, 193


command line option, 190 -termination-depth={N}
-no-auto-inline command line option, 192
command line option, 192 -type-in-type
-no-default-libraries command line option, 193
command line option, 190 -universe-polymorphism,
-no-eta-equality -no-universe-polymorphism
command line option, 191 command line option, 193
-no-fast-reduce -verbose={N}, -v={N}
command line option, 192 command line option, 190
-no-flat-split -version, -V
command line option, 191 command line option, 188
-no-forcing -vim
command line option, 192 command line option, 189
-no-import-sorts -warning={GROUP|FLAG}, -W {GROUP|FLAG}
command line option, 193 command line option, 191
-no-libraries -with-K
command line option, 190 command line option, 191
-no-main -with-compiler={PATH}
command line option, 189 command line option, 189
-no-pattern-matching -without-K
command line option, 191 command line option, 191
-no-positivity-check -vprofile.definitions:10
command line option, 191 command line option, 229
-no-print-pattern-synonyms -vprofile.modules:10
command line option, 192 command line option, 229
-no-projection-like -vprofile:7
command line option, 188 command line option, 229
-no-syntactic-equality
command line option, 192 A
-no-termination-check AbsurdPatternRequiresNoRHS
command line option, 191 command line option, 194
-no-unicode all
command line option, 190 command line option, 193
-omega-in-omega
command line option, 193 C
-only-scope-checking CantGeneralizeOverSorts
command line option, 188 command line option, 194
-overlapping-instances, CoInfectiveImport
-no-overlapping-instances command line option, 194
command line option, 192 command line option
-postfix-projections +RTS -s -RTS, 230
command line option, 190 -allow-exec, 191
-rewriting -allow-incomplete-matches, 191
command line option, 191 -allow-unsolved-metas, 191
-safe -auto-inline, 192
command line option, 193 -caching, -no-caching, 190
-show-implicit -call-by-name, 192
command line option, 190 -compile-dir={DIR}, 189
-show-irrelevant -confluence-check,
command line option, 190 -local-confluence-check, 190
-sized-types, -no-sized-types -copatterns, -no-copatterns, 190
command line option, 193 -count-clusters, 189
-subtyping, -no-subtyping -css={URL}, 189

248 Index
Agda User Manual, Release 2.6.2

-cubical, 190 -subtyping, -no-subtyping, 193


-cumulativity, -no-cumulativity, 193 -termination-depth={N}, 192
-dependency-graph={FILE}, 189 -type-in-type, 193
-double-check, 192 -universe-polymorphism,
-exact-split, -no-exact-split, 191 -no-universe-polymorphism, 193
-experimental-irrelevance, 191 -verbose={N}, -v={N}, 190
-guardedness, -no-guardedness, 192 -version, -V, 188
-help[={TOPIC}], -?[{TOPIC}], 188 -vim, 189
-html, 189 -warning={GROUP|FLAG}, -W
-html-dir={DIR}, 189 {GROUP|FLAG}, 191
-html-highlight=[code,all,auto], 189 -with-K, 191
-ignore-all-interfaces, 189 -with-compiler={PATH}, 189
-ignore-interfaces, 189 -without-K, 191
-include-path={DIR}, -i={DIR}, 189 -vprofile.definitions:10, 229
-injective-type-constructors, 191 -vprofile.modules:10, 229
-instance-search-depth={N}, 192 -vprofile:7, 229
-interaction, 188 AbsurdPatternRequiresNoRHS, 194
-interaction-json, 188 all, 193
-interactive, -I, 188 CantGeneralizeOverSorts, 194
-inversion-max-depth={N}, 192 CoInfectiveImport, 194
-irrelevant-projections, CoverageIssue, 194
-no-irrelevant-projections, 192 CoverageNoExactSplit, 194
-keep-pattern-variables, 191 cpphs, 12
-latex, 189 debug, 12
-latex-dir={DIR}, 189 DeprecationWarning, 194
-library-file={FILE}, 189 EmptyAbstract, 194
-library={DIR}, -l={LIB}, 189 EmptyInstance, 194
-local-interfaces, 190 EmptyMacro, 194
-no-auto-inline, 192 EmptyMutual, 194
-no-default-libraries, 190 EmptyPostulate, 194
-no-eta-equality, 191 EmptyPrimitive, 194
-no-fast-reduce, 192 EmptyPrivate, 194
-no-flat-split, 191 EmptyRewritePragma, 194
-no-forcing, 192 enable-cluster-counting, 12
-no-import-sorts, 193 ignore, 193
-no-libraries, 190 IllformedAsClause, 194
-no-main, 189 InfectiveImport, 194
-no-pattern-matching, 191 InstanceArgWithExplicitArg, 194
-no-positivity-check, 191 InstanceNoOutputTypeName, 194
-no-print-pattern-synonyms, 192 InstanceWithExplicitArg, 194
-no-projection-like, 188 InvalidCatchallPragma, 194
-no-syntactic-equality, 192 InvalidNoPositivityCheckPragma, 194
-no-termination-check, 191 InvalidTerminationCheckPragma, 195
-no-unicode, 190 InversionDepthReached, 195
-omega-in-omega, 193 LibUnknownField, 195
-only-scope-checking, 188 MissingDefinitions, 195
-overlapping-instances, ModuleDoesntExport, 195
-no-overlapping-instances, 192 NotAllowedInMutual, 195
-postfix-projections, 190 NotStrictlyPositive, 195
-rewriting, 191 OldBuiltin, 195
-safe, 193 optimise-heavily, 12
-show-implicit, 190 OverlappingTokensWarning, 195
-show-irrelevant, 190 PolarityPragmasButNotPostulates, 195
-sized-types, -no-sized-types, 193 PragmaCompiled, 195

Index 249
Agda User Manual, Release 2.6.2

PragmaCompileErased, 195 EmptyPrimitive


PragmaNoTerminationCheck, 195 command line option, 194
RewriteMaybeNonConfluent, 195 EmptyPrivate
RewriteNonConfluent, 195 command line option, 194
SafeFlagNonTerminating, 195 EmptyRewritePragma
SafeFlagNoPositivityCheck, 195 command line option, 194
SafeFlagNoUniverseCheck, 195 enable-cluster-counting
SafeFlagPolarity, 195 command line option, 12
SafeFlagPostulate, 195
SafeFlagPragma, 195 I
SafeFlagTerminating, 196 ignore
SafeFlagWithoutKFlagPrimEraseEquality, command line option, 193
196 IllformedAsClause
ShadowingInTelescope, 196 command line option, 194
TerminationIssue, 196 InfectiveImport
UnknownFixityInMixfixDecl, 196 command line option, 194
UnknownNamesInFixityDecl, 196 InstanceArgWithExplicitArg
UnknownNamesInPolarityPragmas, 196 command line option, 194
UnreachableClauses, 196 InstanceNoOutputTypeName
UnsolvedConstraints, 196 command line option, 194
UnsolvedInteractionMetas, 196 InstanceWithExplicitArg
UnsolvedMetaVariables, 196 command line option, 194
UselessAbstract, 196 InvalidCatchallPragma
UselessInline, 196 command line option, 194
UselessInstance, 196 InvalidNoPositivityCheckPragma
UselessPrivate, 196 command line option, 194
UselessPublic, 196 InvalidTerminationCheckPragma
warn., 193 command line option, 195
WithoutKFlagPrimEraseEquality, 196 InversionDepthReached
WrongInstanceDeclaration, 196 command line option, 195
CoverageIssue
command line option, 194 L
CoverageNoExactSplit LibUnknownField
command line option, 194 command line option, 195
cpphs
command line option, 12 M
MissingDefinitions
D command line option, 195
debug ModuleDoesntExport
command line option, 12 command line option, 195
DeprecationWarning
command line option, 194 N
NotAllowedInMutual
E command line option, 195
EmptyAbstract NotStrictlyPositive
command line option, 194 command line option, 195
EmptyInstance
command line option, 194 O
EmptyMacro OldBuiltin
command line option, 194 command line option, 195
EmptyMutual optimise-heavily
command line option, 194 command line option, 12
EmptyPostulate OverlappingTokensWarning
command line option, 194 command line option, 195

250 Index
Agda User Manual, Release 2.6.2

P command line option, 196


PolarityPragmasButNotPostulates UselessAbstract
command line option, 195 command line option, 196
PragmaCompiled UselessInline
command line option, 195 command line option, 196
PragmaCompileErased UselessInstance
command line option, 195 command line option, 196
PragmaNoTerminationCheck UselessPrivate
command line option, 195 command line option, 196
UselessPublic
R command line option, 196
RewriteMaybeNonConfluent
command line option, 195
W
RewriteNonConfluent warn.
command line option, 195 command line option, 193
WithoutKFlagPrimEraseEquality
S command line option, 196
SafeFlagNonTerminating WrongInstanceDeclaration
command line option, 195 command line option, 196
SafeFlagNoPositivityCheck
command line option, 195
SafeFlagNoUniverseCheck
command line option, 195
SafeFlagPolarity
command line option, 195
SafeFlagPostulate
command line option, 195
SafeFlagPragma
command line option, 195
SafeFlagTerminating
command line option, 196
SafeFlagWithoutKFlagPrimEraseEquality
command line option, 196
ShadowingInTelescope
command line option, 196

T
TerminationIssue
command line option, 196

U
UnknownFixityInMixfixDecl
command line option, 196
UnknownNamesInFixityDecl
command line option, 196
UnknownNamesInPolarityPragmas
command line option, 196
UnreachableClauses
command line option, 196
UnsolvedConstraints
command line option, 196
UnsolvedInteractionMetas
command line option, 196
UnsolvedMetaVariables

Index 251

You might also like