Global Instance : forall T, Equivalence (@set_eq T).
Definition set_incl {A} (m1 m2 : set A) :=
forall (a : A), m1 a -> m2 a.
Infix "\subset" := set_incl (at level 70, no associativity) : set_scope.
Notation "[ 'set' x : T | P ]" := (fun x : T => P)
(at level 0, x at level 99, only parsing) : set_scope.
Notation "[ 'set' x | P ]" := [set x : _ | P]
(at level 0, x, P at level 99, format "[ 'set'  x  |  P ]", only parsing) : set_scope.
Definition set0 {T} := [set _ : T | False].
Definition setT {T} := [set _ : T | True].
Notation "[ 'set' : T ]" := (@setT T)
(at level 0, format "[ 'set' :  T ]") : set_scope.
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].

(* Specifications: *)
Lemma subset_eqP T (A B : set T) : (A <--> B) <-> (A \subset B /\ B \subset A).
Lemma subset_trans T (A1 A2 A3 : set T) :
A1 \subset A2 ->
A2 \subset A3 ->
A1 \subset A3.
Lemma subset_refl T (A : set T) : A \subset A.
Lemma subset_singl :
forall {T} (x y : T), [set x] \subset [set y] <-> y = x.
Lemma subset_respects_set_eq_l :
forall (T : Type) (s1 s2 s3 : set T),
s1 <--> s3 -> s3 \subset s2 -> s1 \subset s2.
Lemma subset_respects_set_eq_r :
forall (T : Type) (s1 s2 s3 : set T),
s3 <--> s2 -> s1 \subset s2 -> s1 \subset s3.
Lemma subset_respects_set_eq :
forall {T : Type} {s1 s2 s1' s2' : set T},
s1 <--> s1' ->
s2 <--> s2' ->
s1' \subset s2' ->
s1 \subset s2.
Lemma imsetT T U (f : T -> U) : f @: setT <--> codom f.
Lemma imset_id T (A : set T) : id @: A <--> A.
Lemma imset_incl {T U} (A B : set T) (f : T -> U):
A \subset B ->
f @: A \subset f @: B.
Lemma imset_eq {T U} (A B : set T) (f : T -> U):
A <--> B ->
f @: A <--> f @: B.
Lemma imset_in a b x (f : a -> b) (A : set a) :
x \in A -> f x \in (f @: A).
Lemma imset_id_ext T (A : set T) f : (forall x, f x = x) -> f @: A <--> A.
Lemma imset_eq_ext a b (f g : a -> b) (A : set a) :
(forall x, f x = g x) ->
f @: A <--> g @: A.
Lemma coverE T (A : set T) : \bigcup_(x in A) [set x] <--> A.
Instance set_eq_Proper T U : Proper (@eq (T -> U) ==> set_eq ==> set_eq) imset.
Lemma sub0set T (A : set T) : set0 \subset A.
Lemma bigcup_const A B (P : set B) : inhabited A -> (\bigcup_(_ : A) P) <--> P.
Lemma incl_bigcupr T U A (F : T -> set U) G : (forall x, F x \subset G x) ->
\bigcup_(x in A) F x \subset \bigcup_(x in A) G x.
Lemma eq_bigcupr T U A (F : T -> set U) G : (forall x, F x <--> G x) ->
\bigcup_(x in A) F x <--> \bigcup_(x in A) G x.
Lemma incl_bigcupl T U A B (F : T -> set U) : A \subset B ->
\bigcup_(x in A) F x \subset \bigcup_(x in B) F x.
Lemma eq_bigcupl T U A B (F : T -> set U) : A <--> B ->
\bigcup_(x in A) F x <--> \bigcup_(x in B) F x.
Lemma incl_bigcup a b (x:a) (A : set a) (f:a->set b) :
x \in A ->
f x \subset \bigcup_(x in A) f x.