From Coq Require Import List.
Require Import Crypto.Util.PrimitiveProd.

Import Primitive.Notations.

Fixpoint hlist {A} (P : A -> Type) (ls : list A) : Type
  := match ls return Type with
     | nil => unit
     | cons x xs => P x * @hlist A P xs
     end%type.
Fixpoint split_list {A P} (ls : list (@sigT A P)) : { ls : list A & hlist P ls }
  := match ls with
     | nil => existT _ nil tt
     | cons x xs => let 'existT ls' hls' := @split_list A P xs in existT _ (cons (projT1 x) ls') (projT2 x, hls')
     end.
Fixpoint combine_hlist {A P} (ls : list A) : hlist P ls -> list (@sigT A P)
  := match ls return hlist P ls -> _ with
     | nil => fun _ => nil
     | cons x xs => fun '(Px, Pxs) => existT P x Px :: @combine_hlist A P xs Pxs
     end.
