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.(** 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.

Theorem app_eq_app X (x1 x2 y1 y2: list X) : x1++x2 = y1++y2 -> exists l, (x1 = y1++l /\ y2 = l++x2) \/ (y1 = x1++l /\ x2 = l++y2).