Agda 2.4.0.x regression on termination check - agda

The following code termination checks on Agda 2.3.2.2 but not on 2.4.0.x:
open import Data.Nat
open import Relation.Binary.PropositionalEquality
+-comm : ∀ a b → a + b ≡ b + a
+-comm zero zero = refl
+-comm zero (suc b) = cong suc (+-comm zero b) -- this recursive call is red
+-comm (suc a) zero = cong suc (+-comm a zero)
+-comm (suc a) (suc b) rewrite
+-comm a (suc b)
| +-comm b (suc a) -- and also this one
| +-comm a b = refl
What would be the simplest and least obtrusive way to get rid of the warnings under the newer Agda version?

There were some changes in how the termination checker works (as far as I know, new algorithm was used to make the --termination-depth option obsolete).
The first recursive call is actually fine. It's structurally recursive, but I have no idea why it's being marked.
It's the second one that is causing problems. If you make it structurally recursive, Agda stops complaining. And the fix is actually fairly simple:
+-comm : ∀ a b → a + b ≡ b + a
+-comm zero zero = refl
+-comm zero (suc b) = cong suc (+-comm zero b)
+-comm (suc a) zero = cong suc (+-comm a zero)
+-comm (suc a) (suc b) rewrite
+-comm a (suc b)
| sym (+-comm (suc a) b)
| +-comm a b = refl

Related

How to prove element addition is injective for a cubical finite multi set?

I'm playing around with the type of finite multisets as defined in the cubical standard library here:
https://github.com/agda/cubical/blob/0d272ccbf6f3b142d1b723cead28209444bc896f/Cubical/HITs/FiniteMultiset/Base.agda#L15
data FMSet (A : Type ℓ) : Type ℓ where
[] : FMSet A
_∷_ : (x : A) → (xs : FMSet A) → FMSet A
comm : ∀ x y xs → x ∷ y ∷ xs ≡ y ∷ x ∷ xs
trunc : isSet (FMSet A)
I was able to reproduce the proofs for count extensionality and one of my lemmas I showed that you can remove a element from both sides of an equality and keep the equality.
It was similar to this one: https://github.com/agda/cubical/blob/0d272ccbf6f3b142d1b723cead28209444bc896f/Cubical/HITs/FiniteMultiset/Properties.agda#L183
remove1-≡-lemma : ∀ {a} {x} xs → a ≡ x → xs ≡ remove1 a (x ∷ xs)
remove1-≡-lemma {a} {x} xs a≡x with discA a x
... | yes _ = refl
... | no a≢x = ⊥.rec (a≢x a≡x)
My proofs weren't using the same syntax but in the core libraries syntax it was
cons-path-lemma : ∀ {x} xs ys → (x ∷ xs) ≡ (x ∷ ys) → xs ≡ ys
where the proof is using remove1-≡-lemma path composed on both side of a path which is the argument path functionally composed with remove1 x.
This requires the type of the values to have decidable equality as remove1 doesn't make sense without it. But the lemma itself doesn't mention decidable equality, and so I thought I would try to prove it without having that as a hypothesis. Its now a week later and I'm at my wits end because this seems so 'obvious' but so stubborn to prove.
I'm thinking that my intuition about this being provable may be coming from my classical math background, and so it doesn't follow constructively/contiuously.
So my question is: Is this provable with no assumptions on the element type? If so what would the general structure of the proof look like, I have had trouble getting proofs that want to induct over the two FMSets simultaneously to work (as I'm mostly guessing when trying to get paths to line up as necessary). If it is not provable with no assumptions, is it possible to show that it is equivalent in some form to the necessary assumptions?
I can't offer a proof but an argument why it should be provable without assuming decidability. I think finite multisets can be represented as functions Fin n -> A and equality between multisets f and g is given by a permutation phi : Fin n ~ Fin n, (that is invertible functions on Fin n) such that f o phi = g. Now
(a :: f) 0 = a
(a :: f) (suc i) = f i
If phi : Fin (suc n) ~ Fin (suc n) proves that a :: f = a :: g you can construct a psi : Fin n ~ Fin n which proves that f = g. If phi 0 = 0 then psi n = phi (suc n) otherwise you have to obtain psi by assigning phi^-1 0 to phi 0. However this case analysis is on Fin n.
I think representing the permutation group by swapping adjacent elements is just an inconvenient representation for this problem.

Intuition for difference between eta for function from top and empty functions in Agda

In Agda, it seems it is not possible to show ∀ {A : Set} (f : ⊥ → A) → f ≡ λ ().
However, the seemingly similar term ∀ {A : Set} (f : ⊤ → A) → f ≡ λ _ → f tt can be proven by refl. It can be later used to prove a form of extensionality for ⊤:
ext⊤ : ∀ {A : Set} (f g : ⊤ → A) (H : ∀ x → f x ≡ g x) → f ≡ g
According to this question and answer, the explanation might be in considering different models of type theory. Is it possible to have any intuition on why one is accepted and not the other? Shouldn't f ≡ λ () be some form of eta law?
The ⊤ type has the eta rule which says that any terms with that type are definitionally equal. Hence, f ≡ (λ x → f x) ≡ (λ x → f tt).
⊥ does not have an eta rule in Agda. If f : ⊥ → A, then we only know that f ≡ λ x → f x. λ () is essentially syntactic sugar for ⊥-elim, and f is not definitionally equal to ⊥-elim.
I draw your attention that the first statement is attempting to prove the uniqueness of ⊥ → A. Usually it is true up to isomorphism.
The full correspondence would have been between ∀ {A : Set} (f : ⊤ → A) → f ≡ λ _ → f tt and ∀ {A : Set} (f : ⊥ → A) → f ≡ λ _ → f () - the expression for ⊤ constructs the value tt, so you should be constructing a value for ⊥.
Agda has no means of constructing a value of ⊥, so () is not a valid constructor, it is only a placeholder for what you want.
Although it isn't really pattern-matching, it probably is not harmful to see the use of () as pattern-matching for the empty type - it is allowed to occur only in the pattern-matching positions.
This is intended to show the similarity is superficial, so should amend your intuition about the expressions.
Shouldn't f ≡ λ () be some form of eta law?
It is not clear what you would gain from that. Many things can be proven only up to isomorphism. So, for example, proving the uniqueness of ⊥ → A could correspond to proving the uniqueness of A → ⊤ (not eta-equality of f and λ _ → f tt). Both of these is doable.

What is the proper way to represent a beta-equality type for λ-terms?

I'm looking for a BetaEq type indexed on a : Term, b : Term, that can be inhabited iff a and b are identical, or if they can be turned into identical terms after a series of beta-reductions. For example, suppose id = (lam (var 0)), a = (app id (app id id)) and b = (app (app id id) id); then we should be able to construct a term of type BetaEq a b, because both sides can be reduced to (app id id). I've attempted this:
data BetaEq : (a : Term) -> (b : Term) -> Set where
refl : (a : Term) -> BetaEq a a
redl : (a : Term) -> (b : Term) -> BetaEq (apply-redex a) b -> BetaEq a b
redr : (a : Term) -> (b : Term) -> BetaEq a (apply-redex b) -> BetaEq a b
Where apply-redex performs a single reduction. But that looks a little invented, so I'm not sure if that's the right way to do it. Note that both terms could diverge, so we can't simply consider normal forms. What is the standard way of representing beta-equality?
Assuming well-scoped untyped lambda terms:
open import Data.Fin
open import Data.Nat
data Tm (n : ℕ) : Set where
var : Fin n → Tm n
app : Tm n → Tm n → Tm n
lam : Tm (suc n) → Tm n
And also a definition of single substitution for the outermost variable (but note that it is always preferable to define single substitution in terms of parallel substitution):
sub : ∀ {n} → Tm n → Tm (suc n) → Tm n
Then beta equality is the congruence closure of beta reduction:
data _~_ {n} : Tm n → Tm n → Set where
β : ∀ {t u} → app (lam t) u ~ sub u t
app : ∀ {t t' u u'} → t ~ t' → u ~ u' → app t u ~ app t' u'
lam : ∀ {t t'} → t ~ t' → lam t ~ lam t'
~refl : ∀ {t} → t ~ t
~sym : ∀ {t t'} → t ~ t' → t' ~ t
~trans : ∀ {t t' t''} → t ~ t' → t' ~ t'' → t ~ t''
By congruence closure, we mean the least relation which is:
An equivalence relation, i.e. one which is reflexive, symmetric and transitive.
A congruence with respect to term constructors, i.e. reduction can take place
inside any constructor.
Implied by one-step beta reduction.
Alternatively, you can give a directed notion of reduction, and then define convertibility as reduction to a common term:
open import Data.Product
open import Relation.Binary.Closure.ReflexiveTransitive
-- one-step reduction
data _~>_ {n} : Tm n → Tm n → Set where
β : ∀ {t u} → app (lam t) u ~> sub u t
app₁ : ∀ {t t' u} → t ~> t' → app t u ~> app t' u
app₂ : ∀ {t u u'} → u ~> u' → app t u ~> app t u'
lam : ∀ {t t'} → t ~> t' → lam t ~> lam t'
-- multi-step reduction as reflexive-transitive closure
_~>*_ : ∀ {n} → Tm n → Tm n → Set
_~>*_ = Star _~>_
_~_ : ∀ {n} → Tm n → Tm n → Set
t ~ u = ∃ λ t' → (t ~>* t') × (u ~>* t')
It depends on the situation which version is more convenient. It is the case that the two definitions are equivalent, but AFAIK proving this equivalence is fairly hard, as it requires showing confluence of reduction.

How "with" keyword works in agda ?? and also the code below ??

I am not able to understand it clearly. I tried to learn "with" keyword but there also i have doubt. Please help !!!
I wanted to understand the working of "with" and working of this code.
something-even : ∀ n → Even n ⊎ Even (suc n)
something-even zero = inj₁ zero
something-even (suc n) with something-even n
... | inj₁ x = inj₂ (suc-suc x)
... | inj₂ y = inj₁ y
(this states that either n is even or its successor is even). In fact, thm0 can be implemented without using recursion!
thm0 : ∀ x → ∃ λ y → Even y × x less-than y
thm0 n with something-even n
... | inj₁ x = suc (suc n) , suc-suc x , suc ref
... | inj₂ y = suc n , y , ref
If you are familiar with Haskell, you will notice that in Agda there are no if-statements and no case.
with does pattern-matching of the expression result. For example, with something-even n evaluates something-even n, and then pattern-matches on the following lines with ... | inj₁ x and ... | inj₂ y. These match the expression, to see if its value is constructed using inj₁ or inj₂ constructor, so that the value wrapped by them can be used in the right-hand-side expressions: suc (suc n) , suc-suc x , suc ref uses x determined by inj₁ x, and suc n , y , ref uses y determined by inj₂ y
The actual constructor names come from the definition of ⊎ - see the type of something-even joins types Even n and Even (suc n). So x in inj₁ x corresponds to a value of type Even n for given n, and y in inj₂ y corresponds to a value of type Even (suc n) for the same n.

Non trivial negation in agda

All negations, i.e. conclusions of the form A -> Bottom in agda that I've seen came from absurd pattern matchings. Are there any other cases where it's possible to get negation in agda? Are there any other cases in dependent type theory where it's possible?
Type theories usually don't have a notion of pattern matching (and by extension absurd patterns) and yet they can prove negation of the sort you are describing.
First of all, we'll have to look at data types. Without pattern matching, you characterise them by introduction and elimination rules. Introduction rules are basically constructors, they tell you how to construct a value of that type. On the other hand, elimination rules tell you how to use a value of that type. There are also associated computation rules (β-reduction and sometimes η-reduction), but we needn't deal with those now.
Elimination rules look a bit like folds (at least for positive types). For example, here's how an elimination rule for natural numbers would look like in Agda:
ℕ-elim : ∀ {p} (P : ℕ → Set p)
(s : ∀ {n} → P n → P (suc n))
(z : P 0) →
∀ n → P n
ℕ-elim P s z zero = z
ℕ-elim P s z (suc n) = s (ℕ-elim P s z n)
While Agda does have introduction rules (constructors), it doesn't have elimination rules. Instead, it has pattern matching and as you can see above, we can recover the elimination rule with it. However, we can also do the converse: we can simulate pattern matching using elimination rules. Truth be told, it's usually much more inconvenient, but it can be done - the elimination rule mentioned above basically does pattern matching on the outermost constructor and if we need to go deeper, we can just apply the elimination rule again.
So, we can sort of simulate pattern matching. What about absurd patterns? As an example, we'll take fourth Peano axiom:
peano : ∀ n → suc n ≡ zero → ⊥
However, there's a trick involved (and in fact, it's quite crucial; in Martin-Löf's type theory without universes you cannot do it without the trick, see this paper). We need to construct a function that will return two different types based on its arguments:
Nope : (m n : ℕ) → Set
Nope (suc _) zero = ⊥
Nope _ _ = ⊤
If m ≡ n, we should be able to prove that Nope m n holds (is inhabitated). And indeed, this is quite easy:
nope : ∀ m n → m ≡ n → Nope m n
nope zero ._ refl = _
nope (suc m) ._ refl = _
You can now sort of see where this is heading. If we apply nope to the "bad" proof that suc n ≡ zero, Nope (suc n) zero will reduce to ⊥ and we'll get the desired function:
peano : ∀ n → suc n ≡ zero → ⊥
peano _ p = nope _ _ p
Now, you might notice that I cheated a bit. I used pattern matching even though I said earlier that these type theories don't come with pattern matching. I'll remedy that for the next example, but I suggest you try to prove peano without pattern matching on the numbers (use ℕ-elim given above); if you really want a hardcore version, do it without pattern matching on equality as well and use this eliminator instead:
J : ∀ {a p} {A : Set a} (P : ∀ (x : A) y → x ≡ y → Set p)
(f : ∀ x → P x x refl) → ∀ x y → (p : x ≡ y) → P x y p
J P f x .x refl = f x
Another popular absurd pattern is on something of type Fin 0 (and from this example, you'll get the idea how other such absurd matches could be simulated). So, first of all, we'll need eliminator for Fin.
Fin-elim : ∀ {p} (P : ∀ n → Fin n → Set p)
(s : ∀ {n} {fn : Fin n} → P n fn → P (suc n) (fsuc fn))
(z : ∀ {n} → P (suc n) fzero) →
∀ {n} (fn : Fin n) → P n fn
Fin-elim P s z fzero = z
Fin-elim P s z (fsuc x) = s (Fin-elim P s z x)
Yes, the type is really ugly. Anyways, we're going to use the same trick, but this time, we only need to depend on one number:
Nope : ℕ → Set
Nope = ℕ-elim (λ _ → Set) (λ _ → ⊤) ⊥
Note that is equivalent to:
Nope zero = ⊥
Nope (suc _) = ⊤
Now, notice that both cases for the eliminator above (that is, s and z case) return something of type P (suc n) _. If we choose P = λ n _ → Nope n, we'll have to return something of type ⊤ for both cases - but that's easy! And indeed, it was easy:
bad : Fin 0 → ⊥
bad = Fin-elim (λ n _ → Nope n) (λ _ → _) _
The last thing you might be wondering about is how do we get value of any type from ⊥ (known as ex falso quodlibet in logic). In Agda, we obviously have:
⊥-elim : ∀ {w} {Whatever : Set w} → ⊥ → Whatever
⊥-elim ()
But it turns out that this is precisely the eliminator for ⊥, so it is given when defining this type in type theory.
Are you asking for something like
open import Relation.Nullary
→-transposition : {P Q : Set} → (P → Q) → ¬ Q → ¬ P
→-transposition p→q ¬q p = ¬q (p→q p)
?

Resources