Вам нужно выполнить индукцию как для l1
, так и l
, и использовать H
для устранения невозможных случаев. По сути, я не думаю, что вы можете напрямую выполнить индукцию на H
; Вы должны индуцировать значения, с которыми оно связано, и разрушать H
, пока вы их просматриваете.
Эта лемма здесь должна быть определена первой, хотя. Вы могли бы включить его в доказательство, но его тип достаточно интересен, чтобы стоять в одиночестве:
Theorem subseq_nil (l : list nat): subseq nil l.
Proof.
induction l; constructor; assumption.
Qed.
А потом главное доказательство:
Theorem subseq_snd (l1 l2 l : list nat): subseq (l1 ++ l2) l -> subseq l1 l.
Proof.
(* I like to give parameters on the left side of the :, so I use revert to get the
correct goal for the induction:
forall l, subseq (l1 ++ l2) l -> subseq l1 l *)
revert l; induction l1 as [ | x l1 Hl1]; intro l. (* It's best to give names *)
- intros ?.
apply subseq_nil.
(* Below we get H : subseq (x :: foo) bar. The inversion tactic is like destruct
but it spews out equalities about the type indices instead of leaving you stranded
like induction would. In the l=nil case, inversion produces a contradiction,
because subseq_nil has been ruled out, and, in the l=cons case, it case splits
between subseq_there and subseq_here. *)
- induction l as [ | x' l Hl]; simpl; intro H; inversion H.
+ apply subseq_there.
apply Hl.
assumption.
+ apply subseq_here.
apply Hl1.
assumption.
Qed.