Reputation: 303
I want to prove the lemma below. I am trying to to use tactic 'destruct', but I can't prove it. Please any body guide me how can I prove such lemmas. I can prove it for EmptyString, but not for variables s1 and s2. Thanks
Inductive nat : Set :=
| O : nat
| S : nat -> nat.
Inductive string : Set :=
| EmptyString : string
| String : ascii -> string -> string.
Fixpoint CompStrings (sa : string) (sb : string) {struct sb}: bool :=
match sa with
| EmptyString => match sb with
| EmptyString => true
| String b sb'=> false
end
| String a sa' => match sb with
| EmptyString => false
| String b sb'=> CompStrings sa' sb'
end
end.
Lemma Eq_lenght : forall (s1 s2 : string),
(CompStrings s1 s2) = true -> (Eq_nat (length s1) (length s2)) = true.
Upvotes: 0
Views: 198
Reputation: 9437
First off, let me argue about style. You could have written your function CompStrings as this:
Fixpoint CompStrings' (sa : string) (sb : string) {struct sb}: bool :=
match sa, sb with
| EmptyString, EmptyString => true
| EmptyString, _
| _, EmptyString => false
| String a sa', String b sb'=> CompStrings sa' sb'
end.
I find it easier to read. Here is a proof it's the same as yours, in case you're suspicious:
Theorem CompStrings'ok: forall sa sb, CompStrings sa sb = CompStrings' sa sb.
Proof.
intros. destruct sa, sb; simpl; reflexivity.
Qed.
Now, this will be a two-fold answer. First I'm just going to hint you at the direction for the proof. Then, I'll give you a full proof that I encourage you not to read before you've tried it yourself.
First off, I assumed this definition of length
since you did not provide it:
Fixpoint length (s: string): nat :=
match s with
| EmptyString => O
| String _ rest => S (length rest)
end.
And since I did not have Eq_nat either, I proceeded to prove that the lengths are propositionally equal. It should be fairly trivial to adapt to Eq_nat.
Lemma Eq_length' : forall (s1 s2 : string),
CompStrings s1 s2 = true ->
length s1 = length s2.
Proof.
induction s1.
(* TODO *)
Admitted.
So here is the start! You want to prove a property about the inductive data type string. The thing is, you will want to proceed by case analysis, but if you just do it with destruct
s, it'll never end. This is why we proceed by induction
. That is, you will need to prove that if s1 is the EmptyString, then the property holds
, and that if the property holds for a substring, then it holds for the string with one character added
. The two cases are fairly simple, in each case you can proceed by case analysis on s2 (that is, using destruct
).
Note that I did not do intros s1 s2 C.
before doing induction s1.
. This is fairly important for one reason: if you do it (try!), your induction hypothesis will be too constrained as it will talk about one particular s2
, rather than being quantified by it. This can be tricky when you start doing proofs by induction. So, be sure to try to continue this proof:
Lemma Eq_length'_will_fail : forall (s1 s2 : string),
CompStrings s1 s2 = true ->
length s1 = length s2.
Proof.
intros s1 s2 C. induction s1.
(* TODO *)
Admitted.
eventually, you'll find that your induction hypothesis can't be applied to your goal, because it's speaking about a particular s2
.
I hope you've tried these two exercises.
Now if you're stuck, here is one way to prove the first goal.
Don't cheat! :)
Lemma Eq_length' : forall (s1 s2 : string),
CompStrings s1 s2 = true ->
length s1 = length s2.
Proof.
induction s1.
intros s2 C. destruct s2. reflexivity. inversion C.
intros s2 C. destruct s2. inversion C. simpl in *. f_equal.
exact (IHs1 _ C).
Qed.
To put that in intelligible terms:
let's prove the property forall s2, CompStrings s1 s2 = true -> length s1 = s2
by induction on s1:
in the case where s1 is the EmptyString
, let's look at the shape of s2:
s2 is the EmptyString
, then both lengths are equal to 0, so reflexivity.
;
s2 is a String _ _
, so there is a contradiction in the hypothesis, shown by inversion C.
;
in the case where s1 is a String char1 rest1
, let's look at the shape of s2, supposing the property true for rest:
s2 is the EmptyString
, so there is a contradiction in the hypothesis, show by inversion C.
;
s2 is a String char2 rest2
, then length s1 = S (length rest1)
and length s2 = S (length rest2)
, therefore we need to prove S (length rest1) = S (length rest2)
. Also, the hypothesis C simplifies into C: CompStrings rest1 rest2 = true
. It is the perfect occasion to use the induction hypothesis to prove that length rest1 = length rest2
, and then use that result somehow to prove the goal.
Note that for that last step, there are many ways to proceed to prove S (length rest1) = S (length rest2)
. One of which is using f_equal.
which asks you to prove a pairwise equality between the parameters of the constructor. You could also use a rewrite (IHs1 _ C).
then use reflexivity on that goal.
Hopefully this will help you not only solve this particular goal, but get a first understanding at proofs by induction!
To close on this, here are two interesting links.
This presents the basics of induction (see paragraph "Induction on lists").
This explains, better than me, why and how to generalize your induction hypotheses. You'll learn how to solve the goal where I did intros s1 s2 C.
by putting back the s2
in the goal before starting the induction, using the tactic generalize (dependent)
.
In general, I'd recommend reading the whole book. It's slow-paced and very didactic.
Upvotes: 3