Renaming part of hypothesis in Coq
Question
After destructing n in my proof, I am stuck at the following:
I want to rewrite using IHl, but that is not possible. How do I compose IHl and H' to make sense and prove this theorem?
Answer (Yves)
I am just trying to elaborate on @Arthur answer.
I was able to reproduce your goal with the following script:
Require Import List.n: nat
X: Type
l: list natlength l = n -> nth_error l n = Nonen: nat
X: Type
l: list natlength l = n -> nth_error l n = Nonen: nat
X: Typelength nil = n -> nth_error nil n = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Nonelength (h :: t) = n -> nth_error (h :: t) n = Nonen: nat
X: Typelength nil = n -> nth_error nil n = Nonen: nat
X: Typen = 0 -> length nil = 0 -> nth_error nil 0 = Nonen: nat
X: Typeforall n0 : nat, n = S n0 -> length nil = S n0 -> nth_error nil (S n0) = Nonen: nat
X: Typen = 0 -> length nil = 0 -> nth_error nil 0 = Noneauto.n: nat
X: Typen = 0 -> 0 = 0 -> None = Nonen: nat
X: Typeforall n0 : nat, n = S n0 -> length nil = S n0 -> nth_error nil (S n0) = Nonediscriminate.n: nat
X: Typeforall n0 : nat, n = S n0 -> 0 = S n0 -> None = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Nonelength (h :: t) = n -> nth_error (h :: t) n = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Nonen = 0 -> length (h :: t) = 0 -> nth_error (h :: t) 0 = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Noneforall n0 : nat, n = S n0 -> length (h :: t) = S n0 -> nth_error (h :: t) (S n0) = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Nonen = 0 -> length (h :: t) = 0 -> nth_error (h :: t) 0 = Nonediscriminate.n: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Nonen = 0 -> S (length t) = 0 -> Some h = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = Noneforall n0 : nat, n = S n0 -> length (h :: t) = S n0 -> nth_error (h :: t) (S n0) = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = None
n': nat
E: n = S n'length (h :: t) = S n' -> nth_error (h :: t) (S n') = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = None
n': nat
E: n = S n'S (length t) = S n' -> nth_error t n' = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = None
n': nat
E: n = S n'
E': S (length t) = S n'nth_error t n' = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = None
n': nat
E: n = S n'
E': S (length t) = S n'length t = n' -> nth_error t n' = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = None
n': nat
E: n = S n'length t = n' -> nth_error t n' = Nonen: nat
X: Type
h: nat
t: list nat
IHl: length t = n -> nth_error t n = None
n': nat
E: n = S n'
H': length t = n'nth_error t n' = None
and I agree that this goal cannot be proved. Now, if you instead start your proof with the following text (the Proof and induction lines have to be replaced), it will be provable (I checked).
n: nat
X: Type
l: list natlength l = n -> nth_error l n = NoneX: Type
l: list natforall n : nat, length l = n -> nth_error l n = NoneX: Type
n: natlength nil = n -> nth_error nil n = NoneX: Type
h: nat
t: list nat
IHl: forall n : nat, length t = n -> nth_error t n = None
n: natlength (h :: t) = n -> nth_error (h :: t) n = None
The difference is that the induction hypothesis now has the following statement.
What happened? In the first (faulty) variant, you attempt to prove a statement for all lists whose length is equal to a precise n, because n is fixed before you start the proof by induction. In the second (correct) variant, you attempt to prove a statement for all lists l, and this statement accepts any n as long as length l = n.
In the first variant, n is fixed and the equality length l = n restricts l to be among those that have length precisely n. In the second case, l is chosen first, and n is not fixed, but the equality length l = n restricts n to follow the length of l.
This is called "loading the induction" because the statement forall n, length l = n -> nth_error l n = None is stronger (it is loaded) than the statement that you attempt to prove in the first variant (just for one specific n), but surprisingly it is easier to prove.
Answer (Arthur Azevedo De Amorim)
You cannot, because your induction hypothesis is not general enough. Here is a statement that should be easier to prove:
forall (X : Type) (t : list X), nth_error t (length t) = None