(************************************************************************)
(*         *      The Rocq Prover / The Rocq Development Team           *)
(*  v      *         Copyright INRIA, CNRS and contributors             *)
(* <O___,, * (see version control and CREDITS file for authors & dates) *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
Require Export ListDef.
Set Implicit Arguments.
(* Set Universe Polymorphism. *)
(******************************************************************)
(** * Basics: definition of polymorphic lists and some operations *)
(******************************************************************)
(** The definition of [list] is now in [Init/Datatypes], as well as the definitions of [length] and [app] *)
#[local] Open Scope bool_scope.
Open Scope list_scope.
(** Standard notations for lists. In a special module to avoid conflicts. *)
Module ListNotations.
Notation "[ ]" := nil (format "[ ]") : list_scope.
Notation "[ x ]" := (cons x nil) : list_scope.
Notation "[ x ; y ; .. ; z ]" :=  (cons x (cons y .. (cons z nil) ..))
(format "[ '[' x ;  '/' y ;  '/' .. ;  '/' z ']' ]") : list_scope.
End ListNotations.
Section Lists.
Variable A : Type.
(** Head and tail *)
Definition hd (default:A) (l:list A) :=
match l with
| [] => default
| x :: _ => x
end.
Definition hd_error (l:list A) :=
match l with
| [] => None
| x :: _ => Some x
end.
Definition tl (l:list A) :=
match l with
| [] => []
| _ :: l' => l'
end.
(** The [In] predicate *)
Fixpoint In (a:A) (l:list A) : Prop :=
match l with
| [] => False
| b :: l' => b = a \/ In a l'
end.
End Lists.
Section Facts.
Variable A : Type.
(** *** Generic facts *)

Lemma app_inj_tail :
forall (x y:list A) (a b:A), x ++ [a] = y ++ [b] -> x = y /\ a = b.