(*									*)
(*  PRODUIT CARTESIEN 							*)
(*    On definit ici le produit cartesien de 2 ensembles. Pour cela     *)
(*    on commence par definir (singleprod x E) qui est l'ensemble	*)
(*    des couples (x,y) pour y dans E, puis (prodcart E F) qui est	*)
(*    l'union des (singleprod x F) pour x dans E.			*)
(*									*)

(*
Fixpoint singleprod [x:Elt; A:Ensf] : Ensf :=
  (<Ensf>Case A of
        (* empty *) empty
        (* add   *) [y:Elt][e:Ensf] (add (couple x y) (singleprod x e)) 
  end ).
*)
Fixpoint singleprod (x : Elt) (A : Ensf) {struct A} : Ensf :=
  match A with
  | empty => empty
  | add y e => add (couple x y) (singleprod x e)
  end.(*
Fixpoint prodcart [A:Ensf] : Ensf -> Ensf :=
  [B:Ensf]
  (<Ensf>Case A of
	(* empty *) empty
        (* add   *) [x:Elt][e:Ensf] (union (singleprod x B) (prodcart e B))
  end ).
*)
Fixpoint prodcart (A : Ensf) : Ensf -> Ensf :=
  fun B : Ensf =>
  match A with
  | empty => empty
  | add x e => union (singleprod x B) (prodcart e B)
  end.

(* Specifications: *)
Lemma dans_singleprod : forall (x y x0 : Elt) (b : Ensf), dans (couple x y) (singleprod x0 b) -> x = x0 :>Elt /\ dans y b.
Lemma coupl2 : forall (x y : Elt) (a b : Ensf), dans (couple x y) (prodcart a b) -> dans x a /\ dans y b.
Lemma dans_single : forall (x y : Elt) (a : Ensf), dans y a -> dans (couple x y) (singleprod x a).
Lemma coupl2_inv : forall (x y : Elt) (a b : Ensf), dans x a -> dans y b -> dans (couple x y) (prodcart a b).
Lemma dans_singleprod2 : forall (x x0 : Elt) (b : Ensf), dans x (singleprod x0 b) -> exists y : Elt, x = couple x0 y /\ dans y b.
Lemma coupl3 : forall (a b : Ensf) (x : Elt), dans x (prodcart a b) -> exists x1 : Elt, (exists x2 : Elt, dans x1 a /\ dans x2 b /\ x = couple x1 x2).