(*									*)
(*  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.

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).