Fixpoint compact_prod (T: list Type): Type :=
match T with
| nil => unit
| t :: nil => t
| t :: T0 => (t * compact_prod T0)%type
end.
Fixpoint compact_sum (T: list Type): Type :=
match T with
| nil => unit
| t :: nil => t
| t :: T0 => (t + compact_sum T0)%type
end.
Definition compact_prod_gen {A} {F} (gen: forall a: A, F a) (l: list A): compact_prod (map F l).

(* Specifications: *)
Lemma compact_sum_eq: forall {A} {F1: A -> Type} {F2: A -> Type} (l: list A), (forall a, In a l -> @eq Type (F1 a) (F2 a)) -> @eq Type (compact_sum (map F1 l)) (compact_sum (map F2 l)).
Lemma compact_prod_gen_JMeq: forall {A} {F1} {F2} (gen1: forall a: A, F1 a) (gen2: forall a: A, F2 a)  (l: list A), (forall a, In a l -> JMeq (gen1 a) (gen2 a)) -> JMeq (compact_prod_gen gen1 l) (compact_prod_gen gen2 l).
Lemma compact_sum_gen_JMeq: forall {A} {F1} {F2} (filter: A -> bool) (gen1: forall a: A, F1 a) (gen2: forall a: A, F2 a)  (l: list A), (forall a, In a l -> JMeq (gen1 a) (gen2 a)) -> JMeq (compact_sum_gen filter gen1 l) (compact_sum_gen filter gen2 l).
Lemma aux0: forall {A} {a a0: A}, In a (a0 :: nil) -> a <> a0 -> False.
Lemma compact_prod_proj_gen: forall {A: Type} {F: A -> Type} {l: list A} a d (gen: forall a, F a) (H: forall a b : A, {a = b} + {a <> b}),
In a l ->
proj_compact_prod a l (compact_prod_gen gen l) d H = gen a.
Lemma compact_sum_proj_gen: forall {A: Type} {F: A -> Type} {l: list A} a df (filter: A -> bool) (gen: forall a, F a) (H: forall a b : A, {a = b} + {a <> b}),
compact_sum_inj (compact_sum_gen filter gen l) a H ->
proj_compact_sum a l (compact_sum_gen filter gen l) df H = gen a.
Lemma proj_compact_prod_JMeq: forall A i (l: list A) {F1: A -> Type} {F2: A -> Type} d1 d2 (v1: compact_prod (map F1 l)) (v2: compact_prod (map F2 l)) H,
(forall i, In i l -> @eq Type (F1 i) (F2 i)) ->
In i l ->
JMeq v1 v2 ->
JMeq (proj_compact_prod i l v1 d1 H) (proj_compact_prod i l v2 d2 H).
Lemma proj_compact_sum_JMeq': forall A i (l: list A) {F1: A -> Type} {F2: A -> Type} d1 d2 (v1: compact_sum (map F1 l)) (v2: compact_sum (map F2 l)) H,
(forall i, In i l -> @eq Type (F1 i) (F2 i)) ->
JMeq d1 d2 ->
JMeq v1 v2 ->
JMeq (proj_compact_sum i l v1 d1 H) (proj_compact_sum i l v2 d2 H).
Lemma proj_compact_sum_JMeq: forall A i (l: list A) {F1: A -> Type} {F2: A -> Type} d1 d2 (v1: compact_sum (map F1 l)) (v2: compact_sum (map F2 l)) H,
(forall i, In i l -> @eq Type (F1 i) (F2 i)) ->
compact_sum_inj v1 i H ->
JMeq v1 v2 ->
JMeq (proj_compact_sum i l v1 d1 H) (proj_compact_sum i l v2 d2 H).
Lemma compact_sum_inj_JMeq: forall {A} (l: list A) {F1: A -> Type} {F2: A -> Type} (v1: compact_sum (map F1 l)) (v2: compact_sum (map F2 l)) H,
(forall i, In i l -> @eq Type (F1 i) (F2 i)) ->
JMeq v1 v2 ->
(forall i, compact_sum_inj v1 i H <-> compact_sum_inj v2 i H).
Lemma upd_compact_prod_JMeq: forall A i (l: list A) {F1: A -> Type} {F2: A -> Type} d1 d2 (v1: compact_prod (map F1 l)) (v2: compact_prod (map F2 l)) H,
(forall i, In i l -> @eq Type (F1 i) (F2 i)) ->
JMeq d1 d2 ->
JMeq v1 v2 ->
JMeq (upd_compact_prod l v1 i d1 H) (upd_compact_prod l v2 i d2 H).
Lemma upd_compact_sum_JMeq: forall A i (l: list A) {F1: A -> Type} {F2: A -> Type} d1 d2 (v1: compact_sum (map F1 l)) (v2: compact_sum (map F2 l)) H,
(forall i, In i l -> @eq Type (F1 i) (F2 i)) ->
JMeq d1 d2 ->
JMeq v1 v2 ->
JMeq (upd_compact_sum l v1 i d1 H) (upd_compact_sum l v2 i d2 H).