Section IndexBound.
Context {A : Set}.
Class IndexBound (a : A) (Bound : list A) :=
{ ibound :> nat;
boundi : nth_error Bound ibound = Some a}.
Global Arguments ibound [a Bound] _ .
Global Arguments boundi [a Bound] _.
Record BoundedIndex (Bound : list A) := { bindex :> A; indexb :> IndexBound bindex Bound }.
End IndexBound.
Context {A : Type} {C : Set}.
Variable (projAC : A -> C).
admit.
Defined.
Program Definition nth_Bounded'
(Bound : list A)
(c : C)
(a_opt : option A)
(nth_n : option_map projAC a_opt = Some c)
: A := match a_opt as x
return (option_map projAC x = Some c) -> A with
| Some a => fun _ => a
| None => fun f : None = Some _ => !
end nth_n.
admit.
Defined.
Definition nth_Bounded
(Bound : list A)
(idx : BoundedIndex (map projAC Bound))
: A := nth_Bounded' Bound (nth_error Bound (ibound idx))
(nth_error_map _ _ (boundi idx)).
Program Definition nth_Bounded_ind2
(P : forall As, BoundedIndex (map projAC As)
-> BoundedIndex (map projAC As)
-> A -> A -> Prop)
: forall (Bound : list A)
(idx : BoundedIndex (map projAC Bound))
(idx' : BoundedIndex (map projAC Bound)),
match nth_error Bound (ibound idx), nth_error Bound (ibound idx') with
| Some a, Some a' => P Bound idx idx' a a'
| _, _ => True
end
-> P Bound idx idx' (nth_Bounded _ idx) (nth_Bounded _ idx'):=
fun Bound idx idx' =>
match (nth_error Bound (ibound idx)) as e, (nth_error Bound (ibound idx')) as e'
return
(forall (f : option_map _ e = Some (bindex idx))
(f' : option_map _ e' = Some (bindex idx')),
(match e, e' with
| Some a, Some a' => P Bound idx idx' a a'
| _, _ => True
end)
-> P Bound idx idx'
(match e as e'' return
option_map _ e'' = Some (bindex idx)
-> A
with
| Some a => fun _ => a
| _ => fun f => _
end f)
(match e' as e'' return
option_map _ e'' = Some (bindex idx')
-> A
with
| Some a => fun _ => a
| _ => fun f => _
end f')) with
| Some a, Some a' => fun _ _ H => _
| _, _ => fun f => _
end (nth_error_map _ _ (boundi idx))
(nth_error_map _ _ (boundi idx')).

Lemma nth_Bounded_eq
: forall (Bound : list A)
(idx idx' : BoundedIndex (map projAC Bound)),
ibound idx = ibound idx'
-> nth_Bounded Bound idx = nth_Bounded Bound idx'.