Section RndListElem.
Variable A : Set.
Hypothesis eqd : EqDec A.
Local Open Scope list_scope.
Definition rndListElem(ls : list A) : Comp (option A) :=
match (length ls) with
| O => ret None
| S _ =>
i <-$ [0 .. (length ls));
ret (nth_option ls i)
end.
intuition.
unfold rndListElem.
case_eq (length ls); intuition; wftac.
Qed.
End RndListElem.
Local Open Scope list_scope.
induction ls; intuition; simpl in *.
discriminate.
destruct i.
inversion H; clear H; subst.
intuition.
right.
eapply IHls.
eauto.
Qed.
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.
induction ls; intuition; simpl in *;
intuition.
subst.
destruct (eqd a0 a0); subst.
omega.
intuition.
destruct (eqd a0 a); subst.
omega.
eapply lt_n_S.
eauto.
Qed.
induction ls; intuition; simpl in *.
intuition.
intuition.
subst.
destruct (eqd a0 a0); subst; intuition.
destruct (eqd a0 a); subst; intuition.
Qed.
intuition.
unfold rndListElem.
case_eq (length ls); intuition.
exfalso.
destruct ls; simpl in *; intuition.
eapply getSupport_In_Seq.
eapply in_getSupport_RndNat.
rewrite <- H0.
eapply firstIndexOf_in_lt; eauto.
simpl.
left.
eapply nth_firstIndexOf; trivial.
unfold rndListElem in *.
repeat simp_in_support.
discriminate.
eapply nth_option_In; eauto.
Grab Existential Variables.
apply O.
unfold eq_dec.
eapply (EqDec_dec eqd).
Qed.
induction ls; intuition; simpl in *.
discriminate.
inversion H0; clear H0; subst.
destruct n.
inversion H; clear H; subst.
destruct (eqd a0 a0); subst; intuition.
destruct (eqd a0 a); subst; intuition.
exfalso.
eapply H3.
eapply nth_option_In.
eauto.
Qed.
induction ls; intuition; simpl in *.
omega.
destruct n.
econstructor; eauto.
destruct (IHls n).
omega.
econstructor; eauto.
Qed.
intuition.
unfold rndListElem in *.
case_eq (length ls); intuition.
destruct ls; simpl in *; trivial; discriminate.
rewrite H0 in H.
repeat simp_in_support.
apply RndNat_support_lt in H1.
edestruct (nth_option_some ls); eauto.
rewrite H0.
eauto.
congruence.
subst.
simpl.
intuition.
Qed.

Theorem rndListElem_uniform :
forall (A : Set)(eqd : EqDec A)(ls : list A)(a1 a2 : option A),
NoDup ls ->
In a1 (getSupport (rndListElem _ ls)) ->
In a2 (getSupport (rndListElem _ ls)) ->
evalDist (rndListElem _ ls) a1 ==
evalDist (rndListElem _ ls) a2.