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'.