{-# OPTIONS --cubical-compatible #-}
module Padova2025.ProvingBasics.Connectives.Disjunction where
Disjunction#
In the previous couple sections, we have already stated and proved quite a few results. But we are still lacking the means to express other, quite basic, assertions, such as the following:
Every natural number is even or odd.
∀(n ∈ ℕ). (Even(n) ∨ Odd(n))Every prime number greater than three is one more or one less than a multiple of six.
∀(p ∈ ℙ). (p > 3 ⇒ (6 ∣ p-1 ∨ 6 ∣ p+1))Beyond every natural number, there is a prime number.
∀(n ∈ ℕ). ∃(p ∈ ℕ). (p > n ∧ p ∈ ℙ)
The purpose of this module and the next ones is to fill this gap, and introduce disjunction (∨),
conjunction (∧) and existential quantification (∃). Following the propositions
as types philosophy, we
should for instance introduce a suitable type of witnesses that a given number n
is even or odd. The first result above would then be formalized by a function
which reads an arbitrary number n as input and outputs such a kind of
witness.
Definition: Disjoint union#
For expressing disjunction (∨), for given types A and B we introduce their
disjoint union A ⊎ B:
infixr 1 _⊎_
data _⊎_ (A : Set) (B : Set) : Set where
left : A → A ⊎ B
right : B → A ⊎ B
-- In Haskell, `A ⊎ B` is known as `Either A B`.
In other words, the elements of A ⊎ B are of the form left x for some x : A,
or right y for some y : B. The computational reading is that left is a
function which inputs an element of type A and outputs an element of type A ⊎ B,
and similarly with right. The logical reading is that A implies A or B.
The type of witnesses that a number n is even or odd is then Even n ⊎ Odd n.
Exercise: Tautologies involving disjunction#
open import Padova2025.ProvingBasics.Negation
∨-comm∨-comm : {A B : Set} → A ⊎ B → B ⊎ A
∨-comm = {!!}
∨-assoc∨-assoc : {A B C : Set} → (A ⊎ B) ⊎ C → A ⊎ (B ⊎ C)
∨-assoc = {!!}
∨-elim∨-elim : {A B C : Set} → (A → C) → (B → C) → A ⊎ B → C
∨-elim = {!!}
∨-map∨-map : {A A' B B' : Set} → (A → A') → (B → B') → A ⊎ B → A' ⊎ B'
∨-map = {!!}
∨-codiag∨-codiag : {A : Set} → A ⊎ A → A
∨-codiag = {!!}
∨-not₁∨-not₁ : {A : Set} → A ⊎ ⊥ → A
∨-not₁ = {!!}
∨-not₂∨-not₂ : {A B : Set} → A ⊎ B → ¬ B → A
∨-not₂ = {!!}
Exercise: Even or odd#
open import Padova2025.ProgrammingBasics.Naturals.Base
open import Padova2025.ProvingBasics.EvenOdd
even-or-oddeven-or-odd : (x : ℕ) → Even x ⊎ Odd x
even-or-odd = {!!}
not-odd-implies-evennot-odd-implies-even : (x : ℕ) → ¬ Odd x → Even x
not-odd-implies-even = {!!}
Exercise: Successor of predecessor, revisited#
open import Padova2025.ProgrammingBasics.Naturals.Arithmetic
open import Padova2025.ProvingBasics.Equality.Base
We have already examined the equation succ(pred(a)) = a, which only holds for positive natural numbers. Let us now prove the following variant:
lemma-succ-pred''lemma-succ-pred'' : (a : ℕ) → succ (pred a) ≡ a ⊎ a ≡ zero
lemma-succ-pred'' = {!!}
Exercise: Decidability of equality#
open import Padova2025.ProvingBasics.Equality.General
open import Padova2025.ProvingBasics.Equality.NaturalNumbers
open import Padova2025.ProgrammingBasics.HigherOrder
Every natural number is either zero, or not. This assertion is trivial in classical mathematics for general logical reasons, as it is just an instance of the law of excluded middle (A ∨ ¬A). But there is also a direct proof, a proof which we can implement in Agda without having to postulate the law of excluded middle and thereby destroying Agda’s by-default constructive mode.
zero?zero? : (x : ℕ) → (x ≡ zero) ⊎ ¬ (x ≡ zero)
zero? = {!!}
Unlike a proof relying on the law of excluded middle, this proof can
be run—try it, within the Agda editing session, press C-c C-v
and then input something like zero? four. The zero? function will
then determine whether four is zero, and compute a corresponding
witness.
This proof is a rare instance of an induction proof where the induction step does not use the induction hypothesis.
More generally, we have the result that any two numbers are equal or not:
eq?eq? : (a b : ℕ) → (a ≡ b) ⊎ ¬ (a ≡ b)
eq? = {!!}
Reference solution
eq? : (a b : ℕ) → (a ≡ b) ⊎ ¬ (a ≡ b)
eq? zero zero = left refl
eq? zero (succ b) = right λ ()
eq? (succ a) zero = right λ ()
eq? (succ a) (succ b) = ∨-map (cong succ) (λ f → f ∘ succ-injective) (eq? a b)
-- Alternatively:
-- eq? (succ a) (succ b) with eq? a b
-- ... | left a≡b = left (cong succ a≡b)
-- ... | right a≢b = right λ p → a≢b (succ-injective p)
Exercise: An oracle in the double negation monad#
The following two tautologies are of supreme importance for the purpose of extracting constructive content from classical proofs, and also quite cryptic on first encounter.
¬¬-oracle¬¬-oracle : {A : Set} → ¬ ¬ (A ⊎ ¬ A)
¬¬-oracle = {!!}
¬¬-bind¬¬-bind : {A B : Set} → ¬ ¬ A → (A → ¬ ¬ B) → ¬ ¬ B
¬¬-bind = {!!}
Exercise: Law of excluded middle and double negation elimination#
LEM⇒DNELEM⇒DNE : ((A : Set) → A ⊎ ¬ A) → ((B : Set) → ¬ ¬ B → B)
LEM⇒DNE = {!!}
DNE⇒LEMDNE⇒LEM : ((B : Set) → ¬ ¬ B → B) → ((A : Set) → A ⊎ ¬ A)
DNE⇒LEM = {!!}