I want to destruct my object of type list on two cases like:
H: lst = nil.
H: lst <> nil
I want to destruct my object of type list on two cases like:
H: lst = nil.
H: lst <> nil
If you use destruct lst as [ | fst_elnt lst_tl] eqn:H
you get two goals, in the first goal, you do have the hypothesis that you require.
H : lst = nil
In the second goal, you have an hypothesis of the form
H : lst = fst_elnt :: lst_tl
This is not what you expect for H
, it is actually stronger. To get H
with the expected statement, you can type as follows:
rename H into H'. (* to free the name H *)
assert (H : lst <> nil).
rewrite H'; discriminate.
discriminate
is the basic tactic that expresses the fact that two different constructors of a datatype cannot return equal values.
One possible pattern for your custom case analysis is to provide a custom case analysis lemma, the pattern goes like this:
From Coq Require Import List.
Import ListNotations.
Set Implicit Arguments.
Unset Strict Implicit.
Unset Printing Implicit Defensive.
Inductive list_spec A : list A -> Type :=
| Nil_case : forall x, x = [] -> list_spec x
| Cons_case : forall x, x <> [] -> list_spec x.
Lemma listP A (l : list A) : list_spec l.
Proof. now case l; constructor. Qed.
Lemma foo A (l : list A) : False.
Proof.
case (listP l); intros x Hx.
Then you will get the right hypothesis in your context. Using destruct
instead of case
will clean the spurious l
remaining.
Note that ssreflect
's case
tactic includes special support for this kind of case analysis lemmas, you'd usually do case: l / listP.