Polymorphic Fixpoint nth_error_get_hlist_nth (ls : list iT) (n : nat) {struct ls} :
option {t : iT & hlist ls -> F t} :=
match
ls as ls0
return option {t : iT & hlist ls0 -> F t}
with
| nil => None
| l :: ls0 =>
match
n as n0
return option {t : iT & hlist (l :: ls0) -> F t}
with
| 0 =>
Some (@existT _ (fun t => hlist (l :: ls0) -> F t)
l (@hlist_hd _ _))
| S n0 =>
match nth_error_get_hlist_nth ls0 n0 with
| Some (existT x f) =>
Some (@existT _ (fun t => hlist _ -> F t)
x (fun h : hlist (l :: ls0) => f (hlist_tl h)))
| None => None
end
end
end.

(* Specifications: *)
Theorem nth_error_get_hlist_nth_Some
: forall ls n s,
nth_error_get_hlist_nth ls n = Some s ->
exists pf : nth_error ls n = Some (projT1 s),
forall h, projT2 s h = match pf in _ = t
return match t return Type with
| Some t => F t
| None => unit
end
with
| eq_refl => hlist_nth h n
end.
Theorem nth_error_get_hlist_nth_None
: forall ls n,
nth_error_get_hlist_nth ls n = None <->
nth_error ls n = None.
Lemma nth_error_get_hlist_nth_weaken
: forall ls ls' n x,
nth_error_get_hlist_nth ls n = Some x ->
exists z,
nth_error_get_hlist_nth (ls ++ ls') n =
Some (@existT iT (fun t => hlist (ls ++ ls') -> F t) (projT1 x) z)
/\ forall h h', projT2 x h = z (hlist_app h h').
Lemma nth_error_get_hlist_nth_appL
: forall tvs' tvs n,
n < length tvs ->
exists x,
nth_error_get_hlist_nth (tvs ++ tvs') n = Some x /\
exists y,
nth_error_get_hlist_nth tvs n = Some (@existT _ _ (projT1 x) y) /\
forall vs vs',
(projT2 x) (hlist_app vs vs') = y vs.
Lemma nth_error_get_hlist_nth_appR
: forall tvs' tvs n x,
n >= length tvs ->
nth_error_get_hlist_nth (tvs ++ tvs') n = Some x ->
exists y,
nth_error_get_hlist_nth tvs' (n - length tvs) = Some (@existT _ _ (projT1 x) y) /\
forall vs vs',
(projT2 x) (hlist_app vs vs') = y vs'.