LEM Ain't False
Whether or not the Law of the Excluded Middle is true is the subject of much debate. But we know for sure that it’s not false. Let’s see how to prove this in Lean.
First, the statement of the result:
/-- The Law of the Excluded Middle isn't false. -/
theorem em_not_false : ¬¬(p ∨ ¬p) :=
sorry
That is: it’s not the case that the Law of the Excluded Middle is false.
In Lean (and elsewhere), ¬p
is just an abbreviation for the type p → False
,
which means that em_not_false
is a function:
theorem em_not_false : ¬¬(p ∨ ¬p) :=
fun (hNotEm : ¬(p ∨ ¬p)) =>
sorry
That is, it’s a function that transforms a hypothesis that EM is False
into a proof of False
.
According to the Curry-Howard Isomorphism, fun (h : p) => ...
can be
interpreted as Supposing p
is True
, ...
.
So we’re supposing that EM isn’t True
, and in this hypothetical context we
need to derive a proof of False
.
But before we finish the proof of em_not_false
, we should observe that it’s
obviously true.
And by this I mean that if em
were False
, our whole theorem-proving
edifice would crumble.
To see why, let’s add em_false
as an axiom:
axiom em_false (p: Prop) : ¬(p ∨ ¬p)
What em_false
says is:
For any proposition
p
, given either a proof ofp
or a proof of¬p
, I’ll give you a proof ofFalse
.
Let’s try it out with the simplest proposition of all:
/-- A proof of `False` using `em_false` and a proof of `True`. -/
theorem false_from_true : False :=
em_false True (Or.inl trivial)
And with that the jig is up: if we can prove False
, we can prove anything at
all, a property captured by the elimination principle for False
:
#check False.elim
-- {C : Sort u} → False → C
Using false_from_true
and False.elim
we can prove that 1 is equal to 2:
theorem one_eq_two : 1 = 2 := False.elim false_from_true
That every natural number is equal to 0:
theorem all_zero : ∀ n : Nat, n = 0 := False.elim false_from_true
Along with anything else under the sun.
Finishing the Proof
So having a proof that em
is False
amounts to having a tool of incredible
power.
And that’s exactly what hNotEm
is in our incomplete proof of em_not_false
.
Unforunately it’s not as simple as our proof of false_from_true
, since we can
only use hNotEm
with the parameterized p
proposition.
But it’s not too much more work.
The trick is to use hNotEm
to construct proofs of both ¬p
and ¬¬p
.
Once we have these, we can construct a proof of False
using absurd
.
absurd
implements the Principle of Explosion, also known as “ex falso
quodlibet” (“from a contradiction, anything follows”):
#check absurd
-- {a : Prop} → {b : Sort v} → a → ¬a → b
To see if the general arc of the proof works, we can temporarily strong-arm Lean
using sorry
:
theorem em_not_false : ¬¬(p ∨ ¬p) :=
fun (hNotEm : ¬(p ∨ ¬p)) =>
let hNotP : ¬p := sorry
let hNotNotP : ¬¬p := sorry
absurd hNotP hNotNotP
And now it’s simply a matter of proving hNotP
and hNotNotP
.
Writing out the type of hNotEm
as a function gives a clue to how we might do
this:
hNotEm : (p ∨ ¬p) → False
This says:
Given either a proof of
p
or a proof of¬p
, I’ll give you a proof ofFalse
.
At this point we seem stuck.
We don’t have a proof of p
or ¬p
.
But the trick is to use hNotEm
inside another “hypothetical”.
Specifically, here’s a proof of ¬p
using hNotEm
:
hNotP : ¬p := fun (h : p) => hNotEm (Or.inl h)
We can prove hNotNotP
with the same trick:
hNotNotP : ¬¬p := fun (h : ¬p) => hNotEm (Or.inr h)
And that completes the proof:
theorem em_not_false : ¬¬(p ∨ ¬p) :=
fun (hNotEm : ¬(p ∨ ¬p)) =>
let hNotP : ¬p := fun (h : p) => hNotEm (Or.inl h)
let hNotNotP : ¬¬p := fun (h : ¬p) => hNotEm (Or.inr h)
absurd hNotP hNotNotP
Notes
In Lean, em
is actually a theorem, not an axiom.
It’s proven using the axiom of choice,
a result known as
Diaconescu’s theorem.
The axiom of choice is an axiom in Lean.