Set Implicit Arguments.
Fixpoint fin (n : nat) : Type :=
match n with
| 0 => False
| S n' => option (fin n')
end.
Fixpoint fin_eq_dec (n : nat) : forall (a b : fin n), {a = b} + {a <> b}.
refine
(match n with
| 0 => fun a b : fin 0 => right (match b with end)
| S n' => fun a b : fin (S n') =>
match a, b with
| Some a', Some b' =>
match fin_eq_dec n' a' b' with
| left _ _ => left _
| right _ _ => right _
end
| Some a', None => right _
| None, Some b' => right _
| None, None => left eq_refl
end
end); congruence.
Defined.
Fixpoint all_fin (n : nat) : list (fin n) :=
match n with
| 0 => []
| S n' => None :: map (fun x => Some x) (all_fin n')
end.
Fixpoint fin_to_nat {n : nat} : fin n -> nat :=
match n with
| 0 => fun x : fin 0 => match x with end
| S n' => fun x : fin (S n') =>
match x with
| None => 0
| Some y => S (fin_to_nat y)
end
end.
Definition fin_lt {n : nat} (a b : fin n) : Prop := lt (fin_to_nat a) (fin_to_nat b).

Lemma fin_lt_Some_elim :
forall n (a b : fin n),
@fin_lt (S n) (Some a) (Some b) -> fin_lt a b.