Section setOpsDef.
Context {T U : Type}.
Implicit Types (a x : T) (A B : set T).
Definition set1 a := eq a.
Definition setU A B := [set x | x \in A \/ x \in B].
Definition setI A B := [set x | x \in A /\ x \in B].
Definition codom (f : T -> U) := [set y | exists x, f x = y].
Definition bigcup A (F : T -> set U) := [set x | exists i, i \in A /\ x \in F i].
Definition bigcap (A : set T) (F : T -> set U) :=
[set x | forall (i : T), i \in A -> x \in F i].
End setOpsDef.
Definition imset {T U} (f : T -> U) A := bigcup A (fun x => set1 (f x)).
Definition setX T U (A : set T) (B : set U) := [set x | x.1 \in A /\ x.2 \in B].
Definition imset2 T U V (f : T -> U -> V) A1 A2 :=
imset (prod_curry f) (setX A1 A2).
Definition codom2 T U V (f : T -> U -> V) := codom (prod_curry f).
Notation "[ 'set' a ]" := (set1 a)
(at level 0, a at level 99, format "[ 'set'  a ]") : set_scope.
Notation "[ 'set' a : T ]" := [set (a : T)]
(at level 0, a at level 99, format "[ 'set'  a   :  T ]") : set_scope.
Notation "A :|: B" := (setU A B) (at level 52, left associativity) : set_scope.
Notation "a |: A" := ([set a] :|: A) (at level 52, left associativity) : set_scope.
Notation "A :&: B" := (setI A B) (at level 48, left associativity) : set_scope.
Notation "f @: A" := (imset f A) (at level 24) : set_scope.
Notation "f @2: ( A , B )" := (imset2 f A B)
(at level 24, format "f  @2:  ( A ,  B )") : set_scope.
Notation "\bigcup_ i F" := (bigcup setT (fun i => F))
(at level 41, F at level 41, i at level 0,
format "'[' \bigcup_ i '/  '  F ']'") : set_scope.
Notation "\bigcup_ ( i : t ) F" := (bigcup (@setT t) (fun i => F))
(at level 41, F at level 41, i at level 50,
format "'[' \bigcup_ ( i   :  t ) '/  '  F ']'", only parsing) : set_scope.
Notation "\bigcup_ ( i 'in' A ) F" := (bigcup A (fun i => F))
(at level 41, F at level 41, i, A at level 50,
format "'[' \bigcup_ ( i  'in'  A ) '/  '  F ']'") : set_scope.
Notation "\bigcap_ ( i 'in' A ) F" := (bigcap A (fun i => F))
(at level 41, F at level 41, i, A at level 50,
format "'[' \bigcap_ ( i  'in'  A ) '/  '  F ']'") : set_scope.
Definition lift {T} (S : set T) : set (option T) :=
Some @: S :|: [set None].
Instance set_eq_Proper T U : Proper (@eq (T -> U) ==> set_eq ==> set_eq) imset.
Arguments eq_bigcupl [T U A] B F _ _.
Global Instance eq_bigcup T U : Proper (set_eq ==> pointwise_relation T (@set_eq U) ==> set_eq) bigcup.
Arguments reindex_bigcup [I J K] h [F A] B _ _.
Instance proper_set_incl A :
Morphisms.Proper (set_eq ==> set_eq ==> Basics.impl) (@set_incl A).
Instance eq_setI U : Proper (set_eq ==> set_eq ==> set_eq) (@setI U).

Lemma setI_setU_distr {U} (s1 s2 s3 : set U) :
((s1 :|: s2) :&: s3) <--> ((s1 :&: s3) :|: (s2 :&: s3)).