(** ** Iterated Products *)
Fixpoint Tn (n : nat) (T : Type) : Type :=
match n with
| O => unit
| S n => prod T (Tn n T)
end.
Notation "[ x1 , .. , xn ]" := (pair x1 .. (pair xn tt) .. ).
Fixpoint mk_Tn {T} (n : nat) (u : nat -> T) : Tn n T :=
match n with
| O => (tt : Tn O T)
| S n => (u O, mk_Tn n (fun n => u (S n)))
end.
Fixpoint coeff_Tn {T} {n : nat} (x0 : T) : (Tn n T) -> nat -> T :=
match n with
| O => fun (_ : Tn O T) (_ : nat) => x0
| S n' => fun (v : Tn (S n') T) (i : nat) => match i with
| O => fst v
| S i => coeff_Tn x0 (snd v) i
end
end.

(* Specifications: *)
Lemma mk_Tn_bij {T} {n : nat} (x0 : T) (v : Tn n T) :
mk_Tn n (coeff_Tn x0 v) = v.
Lemma coeff_Tn_bij {T} {n : nat} (x0 : T) (u : nat -> T) :
forall i, (i < n)%nat -> coeff_Tn x0 (mk_Tn n u) i = u i.
Lemma coeff_Tn_ext {T} {n : nat} (x1 x2 : T) (v1 v2 : Tn n T) :
v1 = v2 <-> forall i, (i < n)%nat -> coeff_Tn x1 v1 i = coeff_Tn x2 v2 i.
Lemma mk_Tn_ext {T} (n : nat) (u1 u2 : nat -> T) :
(forall i, (i < n)%nat -> (u1 i) = (u2 i))
<-> (mk_Tn n u1) = (mk_Tn n u2).