How to prove False from obviously contradictory assumptions
Question
Suppose I want to prove following Theorem:
forall n m : nat, S n = m -> 0 = m -> False
This one is trivial since m cannot be both successor and zero, as assumed. However I found it quite tricky to prove it, and I don't know how to make it without an auxiliary lemma:
forall n : nat, 0 = S n -> Falseforall n : nat, 0 = S n -> Falseinversion H. Qed.n: nat
H: 0 = S nFalseforall n m : nat, S n = m -> 0 = m -> Falseforall n m : nat, S n = m -> 0 = m -> Falsen, m: nat
H: S n = m
H0: 0 = mFalsen, m: nat
H: m = S n
H0: 0 = mFalsen, m: nat
H: m = S n
H0: 0 = m0 = S nn, m: nat
H: m = S n
H0: 0 = m0 = mn, m: nat
H: m = S n
H0: 0 = mm = S nassumption.n, m: nat
H: m = S n
H0: 0 = m0 = massumption. Qed.n, m: nat
H: m = S n
H0: 0 = mm = S n
I am pretty sure there is a better way to prove this. What is the best way to do it?
Answer (Arthur Azevedo De Amorim)
You just need to substitute for m in the first equation:
forall n m : nat, S n = m -> 0 = m -> Falseforall n m : nat, S n = m -> 0 = m -> Falsen, m: nat
H1: S n = m
H2: 0 = mFalseinversion H1. Qed.n, m: nat
H1: S n = 0
H2: 0 = mFalse
A: Or a bit more concise yet still explicit:
forall n m : nat, S n = m -> 0 = m -> Falseforall n m : nat, S n = m -> 0 = m -> Falsediscriminate H. Qed.n: nat
H: S n = 0False
less explicit works too:
forall n m : nat, S n = m -> 0 = m -> Falseforall n m : nat, S n = m -> 0 = m -> Falsen, m: nat
H: S n = m
H0: 0 = mFalsediscriminate. Qed.n: nat
H0: 0 = S nFalse
Answer (Gilles 'SO- stop being evil')
There's a very easy way to prove it:
forall n m : nat, S n = m -> 0 = m -> Falsecongruence. Qed.forall n m : nat, S n = m -> 0 = m -> False
The congruence tactic is a decision procedure for ground equalities on uninterpreted symbols. It's complete for uninterpreted symbols and for constructors, so in cases like this one, it can prove that the equality 0 = m is impossible.
Answer (larsr)
It might be useful to know how congruence works.
To prove that two terms constructed by different constructors are in fact different, just create a function that returns True in one case and False in the other cases, and then use it to prove True = False. I think this is explained in Coq'Art
0 <> 10 <> 1C: 0 = 1FalseC: 0 = 1
f:= fun m : nat => match m with | 0 => True | S _ => False end: nat -> PropFalsenow replace False with True by Contra. Qed.C: 0 = 1
f:= fun m : nat => match m with | 0 => True | S _ => False end: nat -> Prop
Contra: f 1 = f 0False