(* given a list of vectors produce the list of all products *)
Fixpoint all_prods (n: nat) (vs: list (vect n)) {struct vs} : list (vect n) :=
match vs with
nil => 1 :: nil
| v::vs1 => let vs1 := all_prods n vs1 in
(map (join n v) vs1 ++ vs1)%list
end.

(* If n is the length of the list of vectors, 2^n is the length of the list of all products *)
Lemma all_prods_length n vs :
length (all_prods n vs) = exp 2 (length vs).