Fixpoint firstIndexOf(A : Set)(eqd : eq_dec A)(ls : list A)(a : A)(def : nat) :=
  match ls with
      | nil => def
      | a' :: ls' =>
        if (eqd a a') then O else (S (firstIndexOf eqd ls' a def))
  end.

(* Specifications: *)
Theorem firstIndexOf_in_lt : forall (A : Set)(eqd : eq_dec A)(ls : list A)(a : A)(def : nat), In a ls -> firstIndexOf eqd ls a def < length ls.
Theorem nth_firstIndexOf : forall (A : Set)(eqd : eq_dec A)(ls : list A)(a : A)(def : nat), In a ls -> nth_option ls (firstIndexOf eqd ls a def) = Some a.
Lemma rndListElem_support: forall (A : Set)(eqd : EqDec A)(ls : list A) a, In a ls <-> In (Some a) (getSupport (rndListElem eqd ls)).
Theorem nth_firstIndexOf_if : forall (A : Set)(eqd : eq_dec A)(ls : list A) n a, nth_option ls n = Some a -> NoDup ls -> firstIndexOf eqd ls a 0 = n.
Theorem nth_option_some : forall (A : Set)(ls : list A) n, n < length ls -> exists a, nth_option ls n = Some a.
Theorem rndListElem_support_None : forall (A : Set) eqd (ls : list A), In None (getSupport (rndListElem eqd ls)) <-> ls = nil.
Lemma not_in_nth_option : forall (A : Set)(ls : list A)(a : A)(i : nat), (~In a ls) -> nth_option ls i = Some a -> False.
Theorem nth_firstIndexOf_None : forall (A : Set)(eqd : eq_dec A)(ls : list A), NoDup ls -> forall (a a' : A) i, In a ls -> i <> firstIndexOf eqd ls a O -> nth_option ls i = Some a' -> a <> a'.
Lemma nth_option_not_None : forall (A : Set)(ls : list A)(i : nat), i < length ls -> nth_option ls i = None -> False.
Theorem rndListElem_uniform_gen : forall (A B : Set)(eqda : EqDec A)(eqdb : EqDec B)(ls1 : list A)(ls2 : list B)(a1 : A)(a2 : B), NoDup ls1 -> NoDup ls2 -> length ls1 = length ls2 -> In a1 ls1 -> In a2 ls2 -> comp_spec (fun x y => x = Some a1 <-> y = Some a2) (rndListElem _ ls1) (rndListElem _ ls2).
Theorem rndListElem_support_exists : forall (A : Set)(eqd : EqDec A)(ls : list A), exists x, In x (getSupport (rndListElem eqd ls)).