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 to agda-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 use agda directly. Here's the file I'm using:
module C1 where
open import Data.Nat
loop : ℕ → ℕ
loop 0 = 0
loop x = loop x
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:
Termination checking failed for the following functions:
loop
Problematic calls:
loop x
(at D:\Agda\tc\C1.agda:7,10-14)
This is indeed compilation error. Such errors prevent us from importing this module from other modules or compiling it. For example, if we add these lines to the file above:
open import IO
main = run (putStrLn "")
And compile the module using C-c C-x C-c, agda-mode complains:
You can only compile modules without unsolved metavariables
or termination checking problems.
Other kinds of compilation errors include type checking problems:
module C2 where
open import Data.Bool
open import Data.Nat
type-error : ℕ → Bool
type-error n = n
__________________________
D:\Agda\tc\C2.agda:7,16-17
ℕ !=< Bool of type Set
when checking that the expression n has type Bool
Failed positivity check:
module C3 where
data Positivity : Set where
bad : (Positivity → Positivity) → Positivity
__________________________
D:\Agda\tc\C3.agda:3,6-16
Positivity is not strictly positive, because it occurs to the left
of an arrow in the type of the constructor bad in the definition of
Positivity.
Or unsolved metavariables:
module C4 where
open import Data.Nat
meta : ∀ {a} → ℕ
meta = 0
__________________________
Unsolved metas at the following locations:
D:\Agda\tc\C4.agda:5,11-12
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 module C1:
data _≡_ {a} {A : Set a} (x : A) : A → Set a where
refl : x ≡ x
test : loop 1 ≡ 1
test = refl
Now, to check that refl is correct expression of that type, agda has to evaluate loop 1. However, since the termination check failed, agda will not unroll loop (and end up in an infinite loop).
However, C-c C-n really forces agda 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:
{-# NO_TERMINATION_CHECK #-}
loop : ℕ → ℕ
loop 0 = 0
loop x = loop x
data _≡_ {a} {A : Set a} (x : A) : A → Set a where
refl : x ≡ x
test : loop 1 ≡ 1
test = refl
Which ends up in:
stack overflow
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:
{-# OPTIONS --no-positivity-check #-}
module Boom where
data Bad (A : Set) : Set where
bad : (Bad A → A) → Bad A
unBad : {A : Set} → Bad A → Bad A → A
unBad (bad f) = f
fix : {A : Set} → (A → A) → A
fix f = (λ x → f (unBad x x)) (bad λ x → f (unBad x x))
loop : {A : Set} → A
loop = fix λ x → x
This one relies on a data type which is not strictly positive. Or we could force agda to accept Set : Set (that is, the type of Set is Set itself) and reconstruct Russell's paradox:
{-# OPTIONS --type-in-type #-}
module Boom where
open import Data.Empty
open import Data.Product
open import Relation.Binary.PropositionalEquality
data M : Set where
m : (I : Set) → (I → M) → M
_∈_ : M → M → Set
a ∈ m I f = Σ I λ i → a ≡ f i
_∉_ : M → M → Set
a ∉ b = (a ∈ b) → ⊥
-- Set of all sets that are not members of themselves.
R : M
R = m (Σ M λ a → a ∉ a) proj₁
-- If a set belongs to R, it does not contain itself.
lem₁ : ∀ {X} → X ∈ R → X ∉ X
lem₁ ((Y , Y∉Y) , refl) = Y∉Y
-- If a set does not contain itself, then it is in R.
lem₂ : ∀ {X} → X ∉ X → X ∈ R
lem₂ X∉X = (_ , X∉X) , refl
-- R does not contain itself.
lem₃ : R ∉ R
lem₃ R∈R = lem₁ R∈R R∈R
-- But R also contains itself - a paradox.
lem₄ : R ∈ R
lem₄ = lem₂ lem₃
loop : {A : Set} → A
loop = ⊥-elim (lem₃ lem₄)
(source). We could also write a variant of Girard's paradox, simplified by A.J.C. Hurkens:
{-# OPTIONS --type-in-type #-}
module Boom where
⊥ = ∀ p → p
¬_ = λ A → A → ⊥
℘_ = λ A → A → Set
℘℘_ = λ A → ℘ ℘ A
U = (X : Set) → (℘℘ X → X) → ℘℘ X
τ : ℘℘ U → U
τ t = λ (X : Set) (f : ℘℘ X → X) (p : ℘ X) → t λ (x : U) → p (f (x X f))
σ : U → ℘℘ U
σ s = s U λ (t : ℘℘ U) → τ t
τσ : U → U
τσ x = τ (σ x)
Δ = λ (y : U) → ¬ (∀ (p : ℘ U) → σ y p → p (τσ y))
Ω = τ λ (p : ℘ U) → ∀ (x : U) → σ x p → p x
loop : (A : Set) → A
loop = (λ (₀ : ∀ (p : ℘ U) → (∀ (x : U) → σ x p → p x) → p Ω) →
(₀ Δ λ (x : U) (₂ : σ x Δ) (₃ : ∀ (p : ℘ U) → σ x p → p (τσ x)) →
(₃ Δ ₂ λ (p : ℘ U) → (₃ λ (y : U) → p (τσ y)))) λ (p : ℘ U) →
₀ λ (y : U) → p (τσ y)) λ (p : ℘ U) (₁ : ∀ (x : U) → σ x p → p x) →
₁ Ω λ (x : U) → ₁ (τσ x)
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 whole loop term into two helps.
The syntax highlighting you are seeing is a compile error. The termination checker's effect is to highlight non-terminating functions in a kind of pink-orange color ("salmon"). You may notice that a module containing such an error cannot be imported from other modules. It can also not be compiled down to Haskell.
So yes, Agda programs always terminate and this is not a bug.
Related
The following encoding of Nats is used in some Cedille sources:
cNat : ★
cNat = ∀ X : ★ . X ➔ (∀ R : ★ . (R ➔ X) ➔ R ➔ X) ➔ X
cZ : cNat
cZ = Λ X . λ z . λ s . z
cS : ∀ A : ★ . (A ➔ cNat) ➔ A ➔ cNat
cS = Λ A . λ e . λ d . Λ X . λ z . λ s . s · A (λ a . e a · X z s) d
I wonder if this is a common encoding used in other languages (Agda, Idris, Coq). If so, how can I interpret it, how it works, and how can I construct members of this type?
I've tried applying cS as in:
c0 = cZ
c1 = (cS -CNat (λ p : CNat . p) C0)
c2 = (cS -CNat (λ p : CNat . p) C1)
c3 = (cS -CNat (λ p : CNat . p) C2)
Which checks, but looks rather weird to me. p could be replaced by any cNat inside lambdas, for example. This doesn't look isomorphic to cNat to me. I guess I don't get this structure.
Edit by JC (too long for a comment, isn't an answer at all). For those who want to experiment, here's an Agda rendering.
module Mendler where
open import Level renaming (suc to lsuc)
open import Data.Nat
cNat : (ℓ : Level) → Set (lsuc ℓ)
cNat ℓ = (X : Set ℓ) → X → ((R : Set ℓ) → (R → X) → R → X) → X
private
variable
ℓ : Level
cZ : cNat ℓ
cZ X z s = z
cS : (A : Set ℓ) → (A → cNat ℓ) → A → cNat ℓ
cS A e d X z s = s A (λ a → e a X z s) d
c0 : cNat 0ℓ
c0 = cZ
c1 : cNat 0ℓ
c1 = cS ℕ (λ _ → c0) 0
For the purpose of a script I would like to query the agda compiler about the definition of a function in an agda source file. I would like to ask the question: does the function named by X rely on a hole, or not? (i.e. is it a "completed proof", or is it a "proof in progress"). Where X is the name of the function in the source file.
For example, take the following example source file:
open import Relation.Binary.PropositionalEquality
postulate
A : Set
x : A
y : A
z : A
q1 : x ≡ y
q2 : y ≡ z
pf1 : x ≡ z
pf1 = trans q1 q2
pf2 : z ≡ x
pf2 rewrite q1 | q2 = refl
I would like to be able to determine (in my script), does pf2 rely on any holes? In this case the answer is no.
Alternatively, suppose that file were something like:
open import Relation.Binary.PropositionalEquality
postulate
A : Set
x : A
y : A
z : A
q1 : x ≡ y
q2 : y ≡ z
pf1 : x ≡ z
pf1 = trans q1 q2
lemma1 : z ≡ y
lemma1 = {!!}
pf2 : z ≡ x
pf2 rewrite q1 = lemma1
Now the answer to the question posed above is "yes": pf2 is incomplete because it relies on a hole (indirectly, through lemma1).
I know that I can find out the answer to the question: are there any functions in this agda source file that rely on holes. When we run the agda compiler on a source file, the return status will be 1 if there are "unsolved interaction metas", and the status will be 0 if everything is completed. However I would like to know the granular information of whether a particular function (by name) within a source file has "unsolved interaction metas".
Is there any way to do this?
I looked through the source code for the interaction mode of agda (the interface used by the agda-mode emacs code), but it seems most of the commands defined for the interaction mode rely on character ranges rather than symbols, so I haven't found a way to get this information from interaction mode.
EDIT: based on user3237465's comment, I looked into using reflection to solve this issue. It seems like it could work but there is an issue with rewrites. For example, suppose we have the following file loaded in emacs:
open import Relation.Binary.PropositionalEquality
open import Agda.Builtin.Reflection
postulate
A : Set
x : A
y : A
z : A
q1 : x ≡ y
q2 : y ≡ z
pf1 : x ≡ z
pf1 = trans q1 q2
lemma1 : z ≡ y
lemma1 = {!!}
pf2 : z ≡ x
pf2 rewrite q1 = lemma1
pf3 : z ≡ x
pf3 = trans lemma1 (sym q1)
-- user3237465 suggested this macro.
-- unfortunately, normalizing `test`
-- using this macro still doesn't show
-- information about the contents of
-- lemma1
macro
actualQuote : Term -> Term -> TC _
actualQuote term hole =
bindTC (normalise term) λ nterm ->
bindTC (quoteTC nterm) (unify hole)
test = actualQuote pf2
test2 = actualQuote pf3
test3 = actualQuote pf1
If I type C-c C-n and enter quoteTC pf3, it outputs quoteTC (trans ?0 (sym q1)). This is what I wanted because it indicates that a the proof depends on a hole.
On the other hand, if I type C-c C-n and enter quoteTC pf2, it outputs quoteTC (pf2 | x | q1). So it appears that the normalization process can't see past a rewrite.
Does anyone know if there is a way around this?
EDIT2: the normalization of pf2 using user3237465's macro is:
def (quote .test4.rewrite-20)
(arg (arg-info visible relevant)
(def (quote x) .Agda.Builtin.List.List.[])
.Agda.Builtin.List.List.∷
arg (arg-info visible relevant)
(def (quote q1) .Agda.Builtin.List.List.[])
.Agda.Builtin.List.List.∷ .Agda.Builtin.List.List.[])
This answer is about using reflection to solve the problem.
The thing missing from your attempt is using getDefinition to look inside defined functions.
Here's a complete example using agda-prelude (https://github.com/UlfNorell/agda-prelude) because I don't have time to figure out to do this with the standard library (exercise for the reader).
open import Prelude
open import Tactic.Reflection
open import Control.Monad.State
open import Container.Traversable
We need to keep track of which names we have already looked inside to avoid looping on recursive functions, so let's use a state monad.
M = StateT (List Name) TC
runM : {A : Set} → M A → TC A
runM m = fst <$> runStateT m []
isVisited : Name → M Bool
isVisited x = gets (elem x)
setVisited : Name → M ⊤
setVisited x = _ <$ modify (x ∷_)
anyM : {A : Set} → (A → M Bool) → List A → M Bool
anyM p xs = foldr _||_ false <$> traverse p xs
Unfortunately we're not going to be able to convince the termination checker that there can only be a finite number of defined functions, so let's cheat. The no-cheat option would be to set a depth limit and return true (or dont-know) if we run out of depth.
{-# TERMINATING #-}
anyMetas : Term → M Bool
checkClause : Clause → M Bool
checkClause (clause ps t) = anyMetas t
checkClause (absurd-clause ps) = return false
checkName : Name → M Bool
checkName f = do
false ← isVisited f
where true → return false
function cs ← lift (getDefinition f)
where _ → return false
anyM checkClause cs
I couldn't resist using do-notation for checkName since it makes the code so much nicer. If you're not building the latest Agda from github, you can use the commented code:
-- caseM isVisited f of λ where
-- true → return false
-- false → setVisited f >>
-- (caseM lift (getDefinition f) of λ where
-- (function cs) → anyM checkClause cs
-- _ → return false)
anyMetaArgs = anyM (anyMetas ∘ unArg)
checkSort : Sort → M Bool
checkSort (set t) = anyMetas t
checkSort (lit n) = return false
checkSort unknown = return false
anyMetas (var x args) = anyMetaArgs args
anyMetas (con c args) = anyMetaArgs args
anyMetas (def f args) = (| checkName f || anyMetaArgs args |)
anyMetas (lam v t) = anyMetas (unAbs t)
anyMetas (pat-lam cs args) = (| anyM checkClause cs || anyMetaArgs args |)
anyMetas (pi a b) = (| anyMetas (unArg a) || anyMetas (unAbs b) |)
anyMetas (agda-sort s) = checkSort s
anyMetas (lit l) = return false
anyMetas (meta x x₁) = return true
anyMetas unknown = return false
With the anyMetas function we can define a macro taking a name and returning a boolean indicating if the name depends on a meta.
macro
dependsOnMeta? : Name → Term → TC ⊤
dependsOnMeta? x hole = unify hole =<< quoteTC =<< runM (anyMetas (def x []))
Your test case now goes through
postulate
A : Set
x : A
y : A
z : A
q1 : x ≡ y
q2 : y ≡ z
pf1 : x ≡ z
pf1 = trans q1 q2
lemma1 : z ≡ y
lemma1 = {!!}
pf2 : z ≡ x
pf2 rewrite q1 = lemma1
pf3 : z ≡ x
pf3 = trans lemma1 (sym q1)
test1 : dependsOnMeta? pf1 ≡ false
test1 = refl
test2 : dependsOnMeta? pf2 ≡ true
test2 = refl
test3 : dependsOnMeta? pf3 ≡ true
test3 = refl
For example, we're proving 2 + 2 != 5:
data _+_≡_ : ℕ → ℕ → ℕ → Set where
znn : ∀ {n} → zero + n ≡ n
sns : ∀ {m n k} → m + n ≡ k → suc m + n ≡ suc k
And I can manually prove it:
2+2≠5 : 2 + 2 ≡ 5 → ⊥
2+2≠5 (sns (sns ()))
But I want the pattern (sns (sns ())) to be generated (just like filling a hole). Are there any ways to achieve that?
I am using Emacs 25 with agda2-mode.
Ok, so let's say you start from this configuration:
2+2≠5 : 2 + 2 ≡ 5 → ⊥
2+2≠5 h = {!!}
In this case you can use emacs' keyboard macros because the sub-term generated by matching on h will also be named h. So using:
<f3> (start recording the macro)
C-c C-f (move to the hole)
C-c C-c h RET (match on h)
<f4> (record the macro)
you've recorded the action of "moving to the first goal an matching on h". You can now keep pressing <f4> until you reach an absurd case.
Here is what I am trying to prove:
A : Type
i : nat
index_f : nat → nat
n : nat
ip : n < i
partial_index_f : nat → option nat
L : partial_index_f (index_f n) ≡ Some n
V : ∀ i0 : nat, i0 < i → option A
l : ∀ z : nat, partial_index_f (index_f n) ≡ Some z → z < i
============================
V n ip
≡ match
partial_index_f (index_f n) as fn
return (partial_index_f (index_f n) ≡ fn → option A)
with
| Some z => λ p : partial_index_f (index_f n) ≡ Some z, V z (l z p)
| None => λ _ : partial_index_f (index_f n) ≡ None, None
end eq_refl
The obvious next step is either rewrite L or destruct (partial_index_f (index_f n). Trying to applying rewrite gives me an error:
Error: Abstracting over the term "partial_index_f (index_f n)"
leads to a term
"λ o : option nat,
V n ip
≡ match o as fn return (o ≡ fn → option A) with
| Some z => λ p : o ≡ Some z, V z (l z p)
| None => λ _ : o ≡ None, None
end eq_refl" which is ill-typed.
I do not understand what is causing this problem. I also would like to understand how I can deal with it in general.
I was able to prove it using the following steps, but I am not sure this is the best way:
destruct (partial_index_f (index_f n)).
inversion L.
generalize (l n0 eq_refl).
intros. subst n0.
replace l0 with ip by apply proof_irrelevance.
reflexivity.
congruence.
In Coq's theory, when you perform a rewrite with an equation, you have to generalize over the side of the equation that you want to replace. In your case, you want to replace partial_index_f (index_f n), so Coq tries to generalize that, as you can tell from the error message you got.
Now, if your goal contains something whose type mentions the thing that you want to replace, you might run into trouble, because this generalization might make the goal become ill-typed. (Notice that that type does not exactly occur in the goal, hence Coq does not try to deal with it like it does when something occurs in the goal.) Going back to your case, your l function has type ∀ z : nat, partial_index_f (index_f n) ≡ Some z → z < i, which mentions partial_index_f (index_f n), the term you want to replace. In the first branch of your match, you apply this function to the o = Some z hypothesis that you abstracted over. On the original goal, o was the thing you wanted to replace, but when Coq tries to generalize, the two do not match anymore, hence the error message.
I can't try to fix the problem on my own, but you can solve issues like this usually by generalizing over the term in your context that mentions the term you are replacing, because then its type will show in the goal, associated to a universally quantified variable. This might not help if your term is defined globally and you need it to have a certain shape after the rewrite in order to be able to perform additional reasoning steps, in which case you will probably have to generalize over the lemmas that you need as well.
I'm trying to representat mod-n counters as a cut of the interval [0, ..., n-1] into two parts:
data Counter : ℕ → Set where
cut : (i j : ℕ) → Counter (suc (i + j))
Using this, defining the two crucial operations is straightforward (some proofs omitted for brevity):
_+1 : ∀ {n} → Counter n → Counter n
cut i zero +1 = subst Counter {!!} (cut zero i)
cut i (suc j) +1 = subst Counter {!!} (cut (suc i) j)
_-1 : ∀ {n} → Counter n → Counter n
cut zero j -1 = subst Counter {!!} (cut j zero)
cut (suc i) j -1 = subst Counter {!!} (cut i (suc j))
The problem comes when trying to prove that +1 and -1 are inverses. I keep running into situations where I need an eliminator for these substs introduced, i.e. something like
subst-elim : {A : Set} → {B : A → Set} → {x x′ : A} → {x=x′ : x ≡ x′} → {y : B x} → subst B x=x′ y ≡ y
subst-elim {A} {B} {x} {.x} {refl} = refl
but this turns out to be (somewhat) begging the question: it isn't accepted by the type checker, because subst B x=x' y : B x' and y : B x...
you can state the type of your subst-elim if you use Relation.Binary.HeterogeneousEquality from the stdlib.
However i'd probably just pattern match on the eventual proof of x ≡ x′ in a with or rewrite clause, so you don't have to make an explicit eliminator and so no typing problem.