(** Linking Heterogeneous Lists and Predicates **)
Section hlist_Forall.
Variable A : Type.
Variable P : A -> Prop.
Fixpoint hlist_Forall ls (hs : hlist P ls) : Forall P ls :=
match hs with
| Hnil => Forall_nil _
| Hcons _ _ H hs' => Forall_cons _ H (hlist_Forall hs')
end.
End hlist_Forall.
(** Heterogeneous Relations **)
Section hlist_rel.
Variable A : Type.
Variables F G : A -> Type.
Variable R : forall x : A, F x -> G x -> Prop.
Inductive hlist_hrel : forall ls, hlist F ls -> hlist G ls -> Prop :=
| hrel_Hnil : hlist_hrel Hnil Hnil
| hrel_Hcons : forall t ts x y xs ys, @R t x y -> @hlist_hrel ts xs ys ->
@hlist_hrel (t :: ts) (Hcons x xs) (Hcons y ys).
End hlist_rel.
Section hlist_rel_map.
Variable A : Type.
Variables F G F' G' : A -> Type.
Variable R : forall x : A, F x -> G x -> Prop.
Variable R' : forall x : A, F' x -> G' x -> Prop.
Variable ff : forall x : A, F x -> F' x.
Variable gg : forall x : A, G x -> G' x.
Hypothesis R_ff_R' :
forall t x y, @R t x y ->
@R' t (ff x) (gg y).

(* Specifications: *)
Theorem hlist_hrel_map
: forall ls xs ys,
@hlist_hrel A F G R ls xs ys ->
@hlist_hrel A F' G' R' ls (hlist_map ff xs) (hlist_map gg ys).
Theorem hlist_hrel_cons
: forall l ls x xs y ys,
@hlist_hrel A F G R (l :: ls) (Hcons x xs) (Hcons y ys) ->
@R l x y /\ @hlist_hrel A F G R ls xs ys.
Theorem hlist_hrel_app
: forall l ls x xs y ys,
@hlist_hrel A F G R (l ++ ls) (hlist_app x xs) (hlist_app y ys) ->
@hlist_hrel A F G R l x y /\ @hlist_hrel A F G R ls xs ys.