0

I want to destruct my object of type list on two cases like:

H: lst = nil.
H: lst <> nil
he11boy
  • 71
  • 3

2 Answers2

1

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.

Yves
  • 3,808
  • 12
  • 12
0

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.

ejgallego
  • 6,709
  • 1
  • 14
  • 29