Fixpoint nth_error (l:list A) (n:nat) {struct n} : option A :=
    match n, l with
      | O, x :: _ => Some x
      | S n, _ :: l' => nth_error l' n
      | _, _ => None
    end.Definition nth_default (default:A) (l:list A) (n:nat) : A :=
    match nth_error l n with
      | Some x => x
      | None => default
    end.

(* Specifications: *)
Lemma nth_default_eq : forall n l (d:A), nth_default d l n = nth n l d.
Lemma nth_In : forall (n:nat) (l:list A) (d:A), n < length l -> In (nth n l d) l.
Lemma In_nth l x d : In x l -> exists n, n < length l /\ nth n l d = x.
Lemma nth_overflow : forall l n d, length l <= n -> nth n l d = d.
Lemma nth_indep : forall l n d d', n < length l -> nth n l d = nth n l d'.
Lemma app_nth1 : forall l l' d n, n < length l -> nth n (l++l') d = nth n l d.
Lemma app_nth2 : forall l l' d n, n >= length l -> nth n (l++l') d = nth (n-length l) l' d.
Lemma app_nth2_plus : forall l l' d n, nth (length l + n) (l ++ l') d = nth n l' d.
Lemma nth_middle : forall l l' a d, nth (length l) (l ++ a :: l') d = a.
Lemma nth_split n l d : n < length l -> exists l1, exists l2, l = l1 ++ nth n l d :: l2 /\ length l1 = n.
Lemma nth_ext : forall l l' d d', length l = length l' -> (forall n, n < length l -> nth n l d = nth n l' d') -> l = l'.
Lemma nth_error_In l n x : nth_error l n = Some x -> In x l.
Lemma In_nth_error l x : In x l -> exists n, nth_error l n = Some x.
Lemma In_iff_nth_error l x : In x l <-> exists n, nth_error l n = Some x.
Lemma nth_error_None l n : nth_error l n = None <-> length l <= n.
Lemma nth_error_Some l n : nth_error l n <> None <-> n < length l.
Lemma nth_error_split l n a : nth_error l n = Some a -> exists l1, exists l2, l = l1 ++ a :: l2 /\ length l1 = n.
Lemma nth_error_app1 l l' n : n < length l -> nth_error (l++l') n = nth_error l n.
Lemma nth_error_app2 l l' n : length l <= n -> nth_error (l++l') n = nth_error l' (n-length l).
Lemma nth_error_app l l' n : nth_error (l ++ l') n = if Nat.ltb n (length l) then nth_error l n else nth_error l' (n - length l).
Lemma nth_error_ext l l': (forall n, nth_error l n = nth_error l' n) -> l = l'.
Lemma unfold_nth_error l n : nth_error l n = match n, l with | O, x :: _ => Some x | S n, _ :: l' => nth_error l' n | _, _ => None end.
Lemma nth_error_nil n : nth_error [] n = None.
Lemma nth_error_cons x xs n : nth_error (x :: xs) n = match n with | O => Some x | S n => nth_error xs n end.
Lemma nth_error_0 l : nth_error l O = hd_error l.
Lemma nth_error_S l n : nth_error l (S n) = nth_error (tl l) n.
Lemma nth_error_cons_0 x l : nth_error (cons x l) 0 = Some x.
Lemma nth_error_cons_succ x l n : nth_error (cons x l) (S n) = nth_error l n.
Lemma nth_error_nth : forall (l : list A) (n : nat) (x d : A), nth_error l n = Some x -> nth n l d = x.
Lemma nth_error_nth' : forall (l : list A) (n : nat) (d : A), n < length l -> nth_error l n = Some (nth n l d).
Lemma nth_error_nth_None (l : list A) (n : nat) (d : A) : nth_error l n = None -> nth n l d = d.