(* Here we cheat. It is easier to define the cartesian product using    *)
(* the type theoretical product, i.e. we here use non set-theoretical   *)
(* constructions. We could however use the usual definitions.           *)


Definition Prod (E E' : Ens) : Ens :=
  match E, E' with
  | sup A f, sup A' f' =>
      sup _
        (fun c : prod_t A A' =>
         match c with
         | pair_t a a' => Couple (f a) (f' a')
         end)
  end.

(* Specifications: *)
Theorem Couple_sound_left : forall A A' B : Ens, EQ A A' -> EQ (Couple A B) (Couple A' B).
Theorem Couple_sound_right : forall A B B' : Ens, EQ B B' -> EQ (Couple A B) (Couple A B').
Theorem Couple_IN_Prod : forall E1 E2 E1' E2' : Ens, IN E1' E1 -> IN E2' E2 -> IN (Couple E1' E2') (Prod E1 E2).
Theorem Couple_Prod_IN : forall E1 E2 E1' E2' : Ens, IN (Couple E1' E2') (Prod E1 E2) -> IN E1' E1 /\ IN E2' E2.
Theorem IN_Prod_EXType : forall E E' E'' : Ens, IN E'' (Prod E E') -> EXType _ (fun A : Ens => EXType _ (fun B : Ens => EQ (Couple A B) E'')).
Theorem Couple_sound_left : forall A A' B : Ens, EQ A A' -> EQ (Couple A B) (Couple A' B).
Theorem Couple_sound_right : forall A B B' : Ens, EQ B B' -> EQ (Couple A B) (Couple A B').
Theorem Couple_IN_Prod : forall E1 E2 E1' E2' : Ens, IN E1' E1 -> IN E2' E2 -> IN (Couple E1' E2') (Prod E1 E2).
Theorem Couple_Prod_IN : forall E1 E2 E1' E2' : Ens, IN (Couple E1' E2') (Prod E1 E2) -> IN E1' E1 /\ IN E2' E2.
Theorem IN_Prod_EXType : forall E E' E'' : Ens, IN E'' (Prod E E') -> EXType _ (fun A : Ens => EXType _ (fun B : Ens => EQ (Couple A B) E'')).