It has been stated a few places that all agda programs terminate. However I can construct a function like this:
stall : ∀ n → ℕ
stall 0 = 0
stall x = stall x
The syntax highlighter doesn't seem to like it, but there are no compilation errors.
Computing the normal form of stall 0
results in 0
. Computing the result of stall 1
causes Emacs to hang in what looks a lot like a non-terminating loop.
Is this a bug? Or can Agda sometimes run forever? Or is something more subtle going on?
In fact, there are compilation errors. The
agda
executable finds an error and passes that information toagda-mode
in Emacs, which in turn does the syntax highlighting to let you know there was an error. We can take a look at what happens if we useagda
directly. Here's the file I'm using:Now, we call
agda -i../lib-0.7/src -i. C1.agda
(don't mind the-i
parameters, they just let the executable know where to look for the standard library) and we get the error:This is indeed compilation error. Such errors prevent us from
import
ing this module from other modules or compiling it. For example, if we add these lines to the file above:And compile the module using
C-c C-x C-c
,agda-mode
complains:Other kinds of compilation errors include type checking problems:
Failed positivity check:
Or unsolved metavariables:
Now, you rightly noticed that some errors are "dead ends", while others let you carry on writing your program. That's because some errors are worse than others. For example, if you get unsolved metavariable, chances are that you'll be able to just fill in the missing information and everything will be okay.
As for hanging the compiler: checking or compiling a module shouldn't cause
agda
to loop. Let's try to force the type checker to loop. We'll add more stuff into the moduleC1
:Now, to check that
refl
is correct expression of that type,agda
has to evaluateloop 1
. However, since the termination check failed,agda
will not unrollloop
(and end up in an infinite loop).However,
C-c C-n
really forcesagda
to try to evaluate the expression (you basically tell it "I know what I'm doing"), so naturally you get into an infinite loop.Incidentally, you can make
agda
loop if you disable the termination check:Which ends up in:
As a rule of thumb: if you can make
agda
loop by checking (or compiling) a module without using any compiler pragmas, then this is indeed a bug and should be reported on the bug tracker. That being said, there are few ways to make non-terminating program if you are willing to use compiler pragmas. We've already seen{-# NO_TERMINATION_CHECK #-}
, here are some other ways:This one relies on a data type which is not strictly positive. Or we could force
agda
to acceptSet : Set
(that is, the type ofSet
isSet
itself) and reconstruct Russell's paradox:(source). We could also write a variant of Girard's paradox, simplified by A.J.C. Hurkens:
This one is a real mess, though. But it has a nice property that it uses only dependent functions. Strangely, it doesn't even get past type checking and causes
agda
to loop. Splitting the wholeloop
term into two helps.