How do you determine which terms to call intros on in coq - coq

I am a beginner with coq, so this may be a trivial question. Sometimes I can't figure out which terms I need to call intros on, when writing a Theorem. A simple example,
Theorem silly1 : forall (n m o p : nat),
n = m ->
[n;o] = [n;p] ->
[n;o] = [m;p].
Proof.
intros n m o p eq1 eq2.
rewrite <- eq1.
apply eq2. Qed.
I know based on the goal, that I will probably need to call intros on (n m o p), but why do I need to use it on eq1 and eq2.
Also, in some other Theorems, you may need to use intros on the type parameter, the hypothesis, or the inductive hypothesis. Example
Theorem trans_eq : forall (X:Type) (n m o : X),
n = m -> m = o -> n = o.
Proof.
intros X n m o eq1 eq2. rewrite -> eq1. rewrite -> eq2.
reflexivity. Qed.
Theorem silly3' : forall (n : nat),
(beq_nat n 5 = true -> beq_nat (S (S n)) 7 = true) ->
true = beq_nat n 5 ->
true = beq_nat (S (S n)) 7.
Proof.
intros n eq H.
symmetry in H. apply eq in H. symmetry in H.
apply H. Qed.
So I guess what I'm asking is...when I start proving a theorem, how should I go about reasoning through the goals, to determine which terms I need to call intros on?

An example of what gallais is refering to is this.
Theorem example_1 : forall A B, (A -> B) -> A -> B.
Proof. intros ? ? H1. apply H1. Qed.
Theorem example_2 : forall A B, (A -> B) -> A -> B.
Proof. intros ? ? H1 H2. apply H1. apply H2. Qed.
Print example_1.
Print example_2.
Another example of when it can be problematic is using introduction before using induction. This makes the induction hypothesis different.
Fixpoint reverse_helper {A : Type} (l1 l2 : list A) : list A :=
match l1 with
| nil => l2
| cons x l1 => reverse_helper l1 (cons x l2)
end.
Theorem example_3 : forall A (l1 l2 : list A), reverse_helper l1 l2 = app (reverse_helper l1 nil) l2.
Proof. intros. induction l1. simpl. reflexivity. simpl. try rewrite IHl1. Abort.
Theorem example_4 : forall A (l1 l2 : list A), reverse_helper l1 l2 = app (reverse_helper l1 nil) l2.
Proof. induction l1. intros. simpl. reflexivity. intros. simpl. rewrite (IHl1 (cons a l2)). rewrite (IHl1 (cons a nil)). Admitted.
Otherwise, you should use introduction whenever you can. You won't be able to use whatever is being quantified over or the antecedents of an implication until you do.
By the way
H1 : A1
...
Hn : An
___
B
is equivalent to
H1: A1, ..., Hn: An ⊢ B.
When you prove something interactively, you're using a sequent calculus starting from the conclusion and working your way back to the hypotheses.

Related

Fail to prove a permutation property

I have created this simple type :
Inductive implist : nat -> list nat -> Prop :=
| GSSingle : forall (n:nat), implist n [n]
| GSPairLeft : forall (a b n:nat) (l:list nat), implist n l -> implist n ([a]++[b]++l)
| GSPairRight : forall (a b n:nat) (l:list nat), implist n l -> implist n (l++[a]++[b]).
and I try to prove this permutation lemma :
Lemma permutImplist :
forall (n a b c:nat) (input:list nat), implist n ((a::b::c::input)) <-> implist n ((c::b::a::input)).
I've tried various induction principles on the type itself or the list, but always end up in a dead end.
Can someone help me with this proof ?
Thanks !!
The induction principle of this predicate is not very useful for proving this directly. It is much better to find an alternative formulation of implist to make your proof go through:
From Coq Require Import List PeanoNat Lia.
Import ListNotations.
Inductive implist : nat -> list nat -> Prop :=
| GSSingle : forall (n:nat), implist n [n]
| GSPairLeft : forall (a b n:nat) (l:list nat), implist n l -> implist n ([a]++[b]++l)
| GSPairRight : forall (a b n:nat) (l:list nat), implist n l -> implist n (l++[a]++[b]).
Lemma implist_alt n l :
implist n l <->
exists l1 l2,
l = l1 ++ n :: l2 /\
Nat.even (length l1) = true /\
Nat.even (length l2) = true.
Proof.
split.
- intros H. induction H as [n|a b n l _ IH|a b n l _ IH].
+ exists [], []; intuition.
+ destruct IH as (l1 & l2 & -> & Hl1 & Hl2).
exists (a :: b :: l1), l2; intuition.
+ destruct IH as (l1 & l2 & -> & Hl1 & Hl2).
exists l1, (l2 ++ [a; b]). simpl.
rewrite <- app_assoc, app_length, Nat.add_comm.
intuition.
- intros (l1 & l2 & -> & Hl1 & Hl2).
assert (Hb1 : exists b, length l1 < b) by (exists (S (length l1)); lia).
destruct Hb1 as (b1 & Hb1).
assert (Hb2 : exists b, length l2 < b) by (exists (S (length l2)); lia).
destruct Hb2 as (b2 & Hb2).
revert l1 b2 l2 Hl1 Hl2 Hb1 Hb2.
induction (Nat.lt_wf_0 b1) as [b1 _ IH1].
intros [| x1 [| y1 l1]]; simpl; try easy.
+ intros b2 l2 _ Hl2 _. revert l2 Hl2.
induction (Nat.lt_wf_0 b2) as [b2 _ IH2].
induction l2 as [|x2 l2 _] using rev_ind.
* intros _ _. apply GSSingle.
* induction l2 as [|y2 l2 _] using rev_ind; simpl; try easy.
rewrite !app_length. simpl. rewrite <- Nat.add_assoc, Nat.add_comm. simpl.
intros Hl2 Hb2. rewrite <- app_assoc.
change (n :: l2 ++ [y2] ++ [x2]) with ((n::l2) ++ [y2] ++ [x2]).
apply GSPairRight. apply (IH2 (S (S (length l2)))); eauto; lia.
+ intros b2 l2 Hl1 Hl2 Hb1 Hb2.
apply (GSPairLeft x1 y1). apply (IH1 (S (S (length l1))) Hb1 _ b2); eauto.
Qed.
Lemma permutImplist_aux :
forall (n a b c:nat) (input:list nat), implist n ((a::b::c::input)) -> implist n ((c::b::a::input)).
Proof.
intros n a b c l (l1 & l2 & e & Hl1 & Hl2)%implist_alt.
destruct l1 as [|x l1]; simpl in *.
{ injection e as <- <-; simpl in *.
apply implist_alt. exists [c; b], l; intuition. }
destruct l1 as [|y l1]; simpl in *; try easy.
injection e as <- <- e.
destruct l1 as [|z l1]; simpl in *.
{ injection e as <- <-.
apply implist_alt. exists [], (b :: a :: l); intuition. }
destruct l1 as [|w l1]; simpl in *; try easy.
injection e as <- ->.
apply implist_alt. exists (c :: b :: a :: w :: l1), l2.
intuition.
Qed.
Lemma permutImplist :
forall (n a b c:nat) (input:list nat), implist n ((a::b::c::input)) <-> implist n ((c::b::a::input)).
Proof.
intros n a b c l; split; apply permutImplist_aux.
Qed.
The tricky part, as you can see, is the reverse direction of implist_alt. The ideal way of proving this would be to have an induction principle for lists of even length. Since we do not have this, I have instead used strong induction on the length of the even lists, which works fine as well.
Following the advice about the induction principal for even lists, I've been able to produce a shorter proof for the reverse direction part :
Lemma implist_alt' :
forall (n:nat) (l:list nat), implist n l <-> exists l1 l2, l = l1 ++ n::l2 /\ Nat.Even (length l1) /\ Nat.Even (length l2).
Proof.
split.
- intros H. induction H as [n|a b n l _ IH|a b n l _ IH].
+ exists [], []; intuition; simpl; now exists 0.
+ destruct IH as (l1 & l2 & -> & Hl1 & Hl2).
exists (a :: b :: l1), l2. intuition. simpl. now rewrite Nat.Even_succ_succ.
+ destruct IH as (l1 & l2 & -> & Hl1 & Hl2).
exists l1, (l2 ++ [a; b]). simpl.
rewrite <- app_assoc, app_length, Nat.add_comm.
intuition. simpl. now rewrite Nat.Even_succ_succ.
- intros (l1 & l2 & -> & Hl1 & Hl2).
induction l1 using list_pair_induction.
simpl. now apply (EvenImplist n l2).
simpl in Hl1. rewrite Nat.Even_succ_succ in Hl1. apply IHl1 in Hl1. revert Hl1. now apply (GSPairLeft a b n (l1++n::l2)).
simpl in Hl1. exfalso. now apply Even_1.
Qed.
It uses the following induction principal on lists :
Section list_pair_induction.
Variable P : list nat -> Prop.
Hypothesis Hnil : P nil.
Hypothesis Hddn : forall (l:list nat) (a b:nat) , P l -> P (a::b::l).
Theorem allEven : forall (xs:list nat), even (length xs) = true -> P xs.
Proof.
intro.
remember (length xs) as n eqn : Heqn.
revert n xs Heqn.
induction n as [n IH] using (well_founded_induction lt_wf).
destruct n as [|n].
now destruct xs.
destruct n as [|n].
intros; discriminate.
destruct xs as [|a xs].
intros; discriminate.
destruct xs as [|b xs].
intros; discriminate.
simpl.
intros H1 H2.
apply Hddn.
apply IH with (y := n); auto.
now injection H1.
Qed.
Theorem allEven' : forall (xs:list nat), Nat.Even (length xs) -> P xs.
Proof.
intro.
rewrite <- Nat.even_spec.
apply allEven.
Qed.
Hypothesis Hsingle : forall (n:nat), P (n::nil).
Theorem Hsingle2Hsing : (forall n:nat, P(n::nil) ) -> forall (xs:list nat), (1 = length xs) -> P xs.
Proof.
induction xs.
intro.
exfalso.
simpl in H0.
congruence.
induction xs.
intro.
apply Hsingle.
intro.
exfalso.
simpl in H0.
congruence.
Qed.
Theorem allOdd : forall (xs:list nat), odd (length xs) = true -> P xs.
Proof.
intro.
remember (length xs) as n eqn : Heqn.
revert n xs Heqn.
induction n as [n IH] using (well_founded_induction lt_wf).
destruct n as [|n].
now destruct xs.
destruct n as [|n].
intros.
generalize Heqn.
generalize xs.
generalize Hsingle.
apply Hsingle2Hsing.
destruct xs as [|a xs].
intros; discriminate.
destruct xs as [|b xs].
intros; discriminate.
simpl.
intros H1 H2.
apply Hddn.
apply IH with (y := n); auto.
now injection H1.
Qed.
Hypothesis Hsing : forall (l:list nat) , (1 = length l) -> P (l).
Theorem allOddsing : forall (xs:list nat), odd (length xs) = true -> P xs.
Proof.
intro.
remember (length xs) as n eqn : Heqn.
revert n xs Heqn.
induction n as [n IH] using (well_founded_induction lt_wf).
destruct n as [|n].
now destruct xs.
destruct n as [|n].
intros.
apply Hsing.
assumption.
destruct xs as [|a xs].
intros; discriminate.
destruct xs as [|b xs].
intros; discriminate.
simpl.
intros H1 H2.
apply Hddn.
apply IH with (y := n); auto.
now injection H1.
Qed.
Theorem allOdd' : forall (xs:list nat), Nat.Odd (length xs) -> P xs.
Proof.
intro.
rewrite <- Nat.odd_spec.
apply allOdd.
Qed.
Theorem list_pair_induction : forall (xs:list nat), P xs.
Proof.
intro.
remember (length xs) as n eqn : Heqn.
destruct even_odd_dec with n.
apply allEven'.
rewrite <- Heqn.
assumption.
apply allOdd'.
rewrite <- Heqn.
assumption.
Qed.
End list_pair_induction.

How does one properly simplify a coq goal with a previous lemma?

Why doesn't the last line of my proof shed a successor instead of adding one.
Note: i'm doing these excercises outside of a classroom setting and don't condone people using it to cheat on hw, I just don't know where else to ask it.
From the tactics chapter in Pierce.
Theorem plus_n_n_injective : forall n m,
n + n = m + m ->
n = m.
Proof.
intros n. induction n as [| n'].
intros.
simpl in H.
destruct m.
reflexivity.
discriminate.
intros.
rewrite <- plus_n_Sm in H.
destruct m.
discriminate.
rewrite <- plus_n_Sm in H.
apply S_injective in H.
simpl in H.
apply S_injective in H.
apply S_injective.
where these auxiliary lemmas are used
Theorem S_injective : forall (n m : nat),
S n = S m ->
n = m.
Proof.
intros n m H1.
assert (H2: n = pred (S n)). { reflexivity. }
rewrite H2. rewrite H1. reflexivity.
Qed.
Theorem plus_n_Sm : forall n m : nat,
S (n + m) = n + (S m).
Proof.
intros n m. induction n as [| n' IHn'].
simpl.
reflexivity.
simpl.
rewrite -> IHn'.
reflexivity.
Qed.
If you have a look at the statement of S_injective:
Theorem S_injective : forall (n m : nat),
S n = S m ->
n = m.
you will see it says that to prove n = m it is enough to prove S n = S m.
Before you apply it, you have to prove S n' = S m, and then you say you only need to prove S (S n') = S (S m). It's because apply in the goal is doing some backward thinking.
What you want instead is being able to say n = m -> S n = S m. You can prove the lemma by hand like you did, or you can use the f_equal tactic which works in general to prove f n = f m from n = m for any f (roughly).

even_Sn_not_even_n - apply 1 hypothesis in another

Unfortunately I got stuck again:
Inductive even : nat > Prop :=
| ev_0 : even 0
| ev_SS (n : nat) (H : even n) : even (S (S n)).
Lemma even_Sn_not_even_n : forall n,
even (S n) <-> not (even n).
Proof.
intros n. split.
+ intros H. unfold not. intros H1. induction H1 as [|n' E' IHn].
- inversion H.
- inversion_clear H. apply IHn in H0. apply H0.
+ intros H. induction n as [|n' IHn].
- exfalso. apply H. apply ev_0.
- apply evSS_inv'.
Here is the result:
1 subgoal (ID 179)
n' : nat
H : ~ even (S n')
IHn : ~ even n' -> even (S n')
============================
even n'
As far I could prove it in words:
(n' + 1) is not even according to H. Therefore according to IHn, it is not true that n' is not even (double negation):
IHn : ~ ~ even n'
Unfolding double negation, we conclude that n' is even.
But how to write it in coq?
The usual way to strip double negation is to introduce the "excluded middle" axiom, which is defined under the name classic in Coq.Logic.Classical_Prop, and apply the lemma NNPP.
However, in this particular case, you can use the technique called reflection by showing that the Prop is consistent with a boolean function (you might remember the evenb function introduced earlier in the book).
(Assuming you're at the beginning of IndProp) You'll soon see the following definition later in that chapter:
Inductive reflect (P : Prop) : bool -> Prop :=
| ReflectT (H : P) : reflect P true
| ReflectF (H : ~ P) : reflect P false.
You can prove the statement
Lemma even_reflect : forall n : nat, reflect (even n) (evenb n).
and then use it to move between a Prop and a boolean (which contain the same information i.e. the (non-)evenness of n) at the same time. This also means that you can do classical reasoning on that particular property without using the classic axiom.
I suggest to complete the exercises under Reflection section in IndProp, and then try the following exercises. (Edit: I uploaded the full answer here.)
(* Since `evenb` has a nontrivial recursion structure, you need the following lemma: *)
Lemma nat_ind2 :
forall P : nat -> Prop,
P 0 -> P 1 -> (forall n : nat, P n -> P (S (S n))) -> forall n : nat, P n.
Proof. fix IH 5. intros. destruct n as [| [| ]]; auto.
apply H1. apply IH; auto. Qed.
(* This is covered in an earlier chapter *)
Lemma negb_involutive : forall x : bool, negb (negb x) = x.
Proof. intros []; auto. Qed.
(* This one too. *)
Lemma evenb_S : forall n : nat, evenb (S n) = negb (evenb n).
Proof. induction n.
- auto.
- rewrite IHn. simpl. destruct (evenb n); auto. Qed.
(* Exercises. *)
Lemma evenb_even : forall n : nat, evenb n = true -> even n.
Proof. induction n using nat_ind2.
(* Fill in here *) Admitted.
Lemma evenb_odd : forall n : nat, evenb n = false -> ~ (even n).
Proof. induction n using nat_ind2.
(* Fill in here *) Admitted.
Lemma even_reflect : forall n : nat, reflect (even n) (evenb n).
Proof. (* Fill in here. Hint: You don't need induction. *) Admitted.
Lemma even_iff_evenb : forall n, even n <-> evenb n = true.
Proof. (* Fill in here. Hint: use `reflect_iff` from IndProp. *) Admitted.
Theorem reflect_iff_false : forall P b, reflect P b -> (~ P <-> b = false).
Proof. (* Fill in here. *) Admitted.
Lemma n_even_iff_evenb : forall n, ~ (even n) <-> evenb n = false.
Proof. (* Fill in here. *) Admitted.
Lemma even_Sn_not_even_n : forall n,
even (S n) <-> not (even n).
Proof. (* Fill in here.
Hint: Now you can convert all the (non-)evenness properties to booleans,
and then work with boolean logic! *) Admitted.

How to do induction differently?

I am doing an exercise in Coq and trying to prove if a list equals to its reverse, it's a palindrome. Here is how I define palindromes:
Inductive pal {X : Type} : list X -> Prop :=
| emptypal : pal []
| singlpal : forall x, pal [x]
| inducpal : forall x l, pal l -> pal (x :: l ++ [x]).
Here is the theorem:
Theorem palindrome3 : forall {X : Type} (l : list X),
l = rev l -> pal l.
According to my definition, I will need to do the induction my extracting the front and tail element but apparently coq won't let me do it, and if I force it to do so, it gives an induction result that definitely doesn't make any sense:
Proof.
intros X l H. remember (rev l) as rl. induction l, rl.
- apply emptypal.
- inversion H.
- inversion H.
- (* stuck *)
context:
1 subgoals
X : Type
x : X
l : list X
x0 : X
rl : list X
Heqrl : x0 :: rl = rev (x :: l)
H : x :: l = x0 :: rl
IHl : x0 :: rl = rev l -> l = x0 :: rl -> pal l
______________________________________(1/1)
pal (x :: l)
aparently the inductive context is terribly wrong. is there any way I can fix the induction?
The solution I propose here is probably not the shortest one, but I think it is rather natural.
My solution consists in defining an induction principle on list specialized to your problem.
Consider natural numbers. There is not only the standard induction nat_ind where you prove P 0 and forall n, P n -> P (S n). But there are other induction schemes, e.g., the strong induction lt_wf_ind, or the two-step induction where you prove P 0, P 1 and forall n, P n -> P (S (S n)). If the standard induction scheme is not strong enough to prove the property you want, you can try another one.
We can do the same for lists. If the standard induction scheme list_ind is not enough, we can write another one that works. In this idea, we define for lists an induction principle similar to the two-step induction on nat (and we will prove the validity of this induction scheme using the two-step induction on nat), where we need to prove three cases: P [], forall x, P [x] and forall x l x', P l -> P (x :: l ++ [x']). The proof of this scheme is the difficult part. Applying it to deduce your theorem is quite straightforward.
I don't know if the two-step induction scheme is part of the standard library, so I introduce it as an axiom.
Axiom nat_ind2 : forall P : nat -> Prop, P 0 -> P 1 ->
(forall n : nat, P n -> P (S (S n))) -> forall n : nat, P n.
Then we prove the induction scheme we want.
Lemma list_ind2 : forall {A} (P : list A -> Prop) (P_nil : P [])
(P_single : forall x, P [x])
(P_cons_snoc : forall x l x', P l -> P (x :: l ++ [x'])),
forall l, P l.
Proof.
intros. remember (length l) as n. symmetry in Heqn. revert dependent l.
induction n using nat_ind2; intros.
- apply length_zero_iff_nil in Heqn. subst l. apply P_nil.
- destruct l; [discriminate|]. simpl in Heqn. inversion Heqn; subst.
apply length_zero_iff_nil in H0. subst l. apply P_single.
- destruct l; [discriminate|]. simpl in Heqn.
inversion Heqn; subst. pose proof (rev_involutive l) as Hinv.
destruct (rev l). destruct l; discriminate. simpl in Hinv. subst l.
rewrite app_length in H0.
rewrite PeanoNat.Nat.add_comm in H0. simpl in H0. inversion H0.
apply P_cons_snoc. apply IHn. assumption.
Qed.
You should be able to conclude quite easily using this induction principle.
Theorem palindrome3 : forall {X : Type} (l : list X),
l = rev l -> pal l.

Coq: Problems with List In inductive

I'm new to Coq, but with some effort I was able to prove various inductive lemmas. However I get stuck on all exercises that uses the following inductive definition:
Inductive In (A:Type) (y:A) : list A -> Prop :=
| InHead : forall xs:list A, In y (cons y xs)
| InTail : forall (x:A) (xs:list A), In y xs -> In y (cons x xs).
The furthest i got was with the following lemma:
Lemma my_In_rev : forall (A:Type) (x:A) (l:list A), In x l -> In x (rev l).
Proof.
induction l.
simpl.
trivial.
simpl.
intros.
The following two lemmas I cant get past the first steps, because I get stuck on the exists goal right after using intros.
Lemma my_In_map : forall (A B:Type) (y:B) (f:A->B) (l:list A), In y (map f l) -> exists x : A, In x l /\ y = f x.
Lemma my_In_split : forall (A:Type) (x:A) (l : list A), In x l -> exists l1, exists l2, l = l1 ++ (x::l2).
Proof.
Any help would be appreciated!
For your first lemma, I added two simple sublemmas (that you can find in the list library).
The two others are more straightforward.
Require Import List.
Lemma In_concat_l: forall (A: Type) (l1 l2: list A) (x:A),
In x l1 -> In x (l1 ++ l2).
Proof.
intros A.
induction l1 as [ | hd tl hi ]; intros l2 x hIn; simpl in *.
- contradiction.
- destruct hIn.
+ left; assumption.
+ right; now apply hi.
Qed.
Lemma In_concat_r: forall (A: Type) (l1 l2: list A) (x:A),
In x l2 -> In x (l1 ++ l2).
intros A.
induction l1 as [ | hd tl hi ]; intros l2 x hIn; simpl in *.
- assumption.
- right; now apply hi.
Qed.
Lemma my_In_rev : forall (A:Type) (x:A) (l:list A), In x l -> In x (rev l).
Proof.
intros A x l.
induction l as [ | hd tl hi ]; intros hIn; simpl in *.
- contradiction.
- destruct hIn.
+ apply In_concat_r.
rewrite H.
now constructor.
+ apply In_concat_l.
now apply hi.
Qed.
Lemma my_In_map : forall (A B:Type) (y:B) (f:A->B) (l:list A), In y (map f l) -> exists x : A, In x l /\ y = f x.
Proof.
intros A B y f l.
induction l as [ | hd tl hi]; intros hIn; simpl in *.
- contradiction.
- destruct hIn.
+ exists hd; split.
left; reflexivity.
symmetry; assumption.
+ destruct (hi H) as [x0 [ h1 h2]].
exists x0; split.
right; assumption.
assumption.
Qed.
Lemma my_In_split : forall (A:Type) (x:A) (l : list A), In x l -> exists l1, exists l2, l = l1 ++ (x::l2).
Proof.
intros A x l.
induction l as [ | hd tl hi]; intros hIn; simpl in *.
- contradiction.
- destruct hIn.
rewrite H.
exists nil; exists tl; simpl; reflexivity.
destruct (hi H) as [ l1 [ l2 h ]].
exists (hd :: l1); exists l2.
rewrite <- app_comm_cons; rewrite h.
reflexivity.
Qed.
I won't say it's less complex than Rui's answer, but I find this solution a little bit easier to understand. But in the end, they are relatively close.
Cheers,
V.
When the goal is existentially quantified, you have to give a concrete example of an object with the stated property, and when a hypothesis is existentially quantified, you're allowed to assume one such object exists and introduce it. See FAQs 47, 53, and 54. By the way, an In predicate is already defined in Coq.Lists.List. Check it out here. A reference for Coq tactics is here.
A proof of the first lemma:
Require Import Coq.Lists.List.
Require Import Coq.Setoids.Setoid.
Inductive In {A : Type} (y : A) : list A -> Prop :=
| InHead : forall xs : list A, In y (cons y xs)
| InTail : forall (x : A) (xs : list A), In y xs -> In y (cons x xs).
Lemma L1 : forall (t1 : Type) (l1 : list t1) (o1 o2 : t1),
In o1 (o2 :: l1) <-> o1 = o2 \/ In o1 l1.
Proof.
intros t1 l1 o1 o2. split.
intros H1. inversion H1 as [l2 [H3 H4] | o3 l2 H2 [H3 H4]].
left. reflexivity.
right. apply H2.
intros H1. inversion H1 as [H2 | H2].
rewrite H2. apply InHead.
apply InTail. apply H2.
Qed.
Lemma my_In_map : forall (A B : Type) (l : list A) (y : B) (f : A -> B),
In y (map f l) -> exists x : A, In x l /\ y = f x.
Proof.
intros A B. induction l as [| z l H1].
intros y f H2. simpl in *. inversion H2.
intros y f H2. simpl in *. rewrite L1 in H2. inversion H2 as [H3 | H3].
exists z. split.
apply InHead.
apply H3.
assert (H4 := H1 _ _ H3). inversion H4 as [x [H5 H6]]. exists x. split.
rewrite L1. right. apply H5.
apply H6.
Qed.