(* spec    proof comments *)
(*   24       40      632 pcp_cfg.v *)
(* Lemma list_prefix_double_inv X (x1 x2 : X) A A' B B' : *)
(*   ~ x1 el A -> ~ x1 el A' -> ~ x2 el A -> ~ x2 el A' -> A ++ x1 :: B = A' ++ x2 :: B' -> A = A' /\ B = B'. *)
(* Proof. *)
(*   intro. revert A' B B'. *)
(*   induction A; intros. *)
(*   - destruct A'; inv H3; firstorder. *)
(*   - destruct A';  inv H3. firstorder. *)
(*     eapply IHA in H6; try now firstorder. intuition congruence. *)
(* Qed. *)
(* Lemma list_prefix_inv X (x : X) A A' B B' : *)
(*   ~ x el A -> ~ x el A' -> A ++ x :: B = A' ++ x :: B' -> A = A' /\ B = B'. *)
(* Proof. *)
(*   intros. eapply list_prefix_double_inv; eauto. *)
(* Qed. *)
(* Lemma list_snoc_inv X (A : list X) : *)
(*   A = [] \/ exists x A', A = A' ++ [x]. *)
(* Proof. *)
(*   induction A. *)
(*   - firstorder. *)
(*   - destruct IHA as [-> | (? & ? & ->)]. right. now exists a, []. *)
(*     right. now exists x, (a :: x0). *)
(* Qed. *)
(* Lemma map_injective X Y (f : X -> Y) A B : *)
(*   (forall x y, f x = f y -> x = y) -> map f A = map f B -> A = B. *)
(* Proof. *)
(*   revert B. induction A; intros [] H H0; inv H0; firstorder congruence. *)
(* Qed. *)

(* Specifications: *)
Lemma in_concat_iff X (l : list (list X)) x :
x el concat l <-> exists l', x el l' /\ l' el l.