Section FindMin.
Variable A : Type.
Variable f : A -> nat.
(* Search in the list for the min with respect to a valuation function f *)
Fixpoint find_min (l : list A) : option (nat * A) :=
match l with
| nil => None
| a :: l1 =>
match find_min l1 with
| None => Some (f a, a)
| Some (n1, b) =>
let n2 := f a in
match le_lt_dec n1 n2 with
| left _ => Some (n1, b)
| right _ => Some (n2, a)
end
end
end.
Proof using.
intros l; elim l; simpl in |- *; auto.
intros a l0; case (find_min l0); simpl in |- *.
intros p; case p; simpl in |- *.
intros n b ((H1, H2), H3); case (le_lt_dec n (f a)); simpl in |- *.
intros H4; split; auto.
intros c [H5| H5]; auto.
rewrite <- H2; rewrite <- H5; auto.
intros H4; split; auto.
intros c [H5| H5]; auto.
rewrite <- H5; auto.
apply le_trans with (f b); auto.
rewrite <- H2; auto with arith.
intros H; rewrite H; split; simpl in |- *; auto.
intros c [H1| H1]; rewrite H1 || case H1; auto.
Qed.
(* Search in the list for the max with respect to a valuation function f *)
Fixpoint find_max (l : list A) : option (nat * A) :=
match l with
| nil => None
| a :: l1 =>
match find_max l1 with
| None => Some (f a, a)
| Some (n1, b) =>
let n2 := f a in
match le_lt_dec n1 n2 with
| right _ => Some (n1, b)
| left _ => Some (n2, a)
end
end
end.

Theorem find_max_correct :
forall l : list A,
match find_max l with
| None => l = nil
| Some (a, b) => (In b l /\ a = f b) /\ (forall c : A, In c l -> f c <= f b)
end.