Reputation: 4062
Inductive bar {X : Type} : list X -> Prop :=
| bar_nil : bar []
| bar_fst : forall x l, bar (rev l ++ l) -> bar (rev l ++ [x] ++ l)
| bar_snd : forall x l, bar (rev l ++ [x] ++ l) -> bar (rev l ++ [x; x] ++ l).
Axiom bar_surround :
forall X x (l : list X),
bar l -> bar ([x] ++ l ++ [x]).
Inductive list_last {X : Type} : list X -> Prop :=
| ll_nil : list_last []
| ll_snoc : forall l x, list_last l -> list_last (l ++ [x]).
Axiom ll_app :
forall X (a b : list X),
list_last a -> list_last b -> list_last (a ++ b).
Axiom ll_from_list :
forall {X} (l : list X),
list_last l.
Axiom app_head_eq :
forall X (a b c : list X),
a ++ c = b ++ c -> a = b.
Theorem foo :
forall X (l: list X), l = rev l -> bar l.
Proof.
intros.
induction l.
- constructor.
- assert (Hll := ll_from_list l).
inversion Hll.
+ apply (bar_fst x []). apply bar_nil.
+ rewrite <- H1 in H.
simpl in H.
rewrite rev_app_distr in H.
rewrite <- app_assoc in H.
simpl in H.
inversion H.
apply app_head_eq in H4.
apply bar_surround.
1 subgoal
X : Type
x : X
l, l0 : list X
x0 : X
H : x :: l0 ++ [x0] = x0 :: rev l0 ++ [x]
IHl : l = rev l -> bar l
Hll : list_last l
H0 : list_last l0
H1 : l0 ++ [x0] = l
H3 : x = x0
H4 : l0 = rev l0
______________________________________(1/1)
bar l0
I am only a step away from getting this exercise solved, but I do not know how to do the induction step. Note that IHl
is useless here and replacing induction on l
with induction on Hll
would have a similar problem. In both cases, the inductive hypothesis would expect a call with a one step decrease while I need two - one with the item taken from both the start and the end of the list on both sides of the equality.
Consider that the type of the function I am trying to prove is forall X (l: list X), l = rev l -> bar l
and I have l0 = rev l0 -> bar l0
in the goal here. l0
is a decreased argument thereby making the recursive call safe.
What should I do here?
Upvotes: 1
Views: 90
Reputation: 4062
Here is how to implement the first part of what was suggested in the other answer. I can confirm that with this, solving the exercise is quite simple. That having said, I am interested how to solve the above using straightforward induction. Having to implement delist
and its functions is more complicated than I'd prefer.
Inductive delist {A : Type} : list A -> Prop :=
| delist_nil : delist []
| delist_one x : delist [x]
| delist_wrap x y l : delist l -> delist (x :: l ++ [y]).
Theorem delist_cons {A} :
forall x (l : list A),
delist l -> delist (x :: l).
Proof.
intros.
generalize dependent x.
induction H; intros.
- constructor.
- replace [x; x0] with (x :: [] ++ [x0]).
2 : { reflexivity. }
+ apply delist_wrap with (l := []). constructor.
- replace (x0 :: x :: l ++ [y]) with (x0 :: (x :: l) ++ [y]).
2 : { reflexivity. }
constructor.
apply IHdelist.
Qed.
Theorem delist_from_list {A} :
forall l : list A,
delist l.
Proof.
induction l.
- constructor.
- assert (ll := ll_from_list l).
destruct ll.
+ constructor.
+ apply delist_cons. assumption.
Qed.
Upvotes: 0
Reputation: 33399
You can prove the following inductive predicate:
Inductive delist {A : Type} : list A -> Prop :=
| delist_nil : delist []
| delist_one x : delist [x]
| delist_cons x y l : delist l -> delist (x :: l ++ [y])
.
Theorem all_delist {A} : forall xs : list A, delist xs.
Then in your final theorem, induction on delist xs
will split into the cases you need.
Another solution is by strong induction on the length of the list:
Lemma foo_len X : forall (n : nat) (l: list X), length l <= n -> l = rev l -> bar l.
Proof.
induction n.
(* Nat.le_succ_r from the Arith module is useful here *)
...
Qed.
(* Final theorem *)
Theorem foo X : forall (l : list X), l = rev l -> bar l.
Proof.
intros; apply foo_len; auto.
Qed.
This is a more common and systematic principle than delist
, but you will need to work more than the ad-hoc inductive type above to use the induction hypothesis in the main proof.
Upvotes: 1