Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

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)

?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top