Require Export Ensembles.
Require Export Image.
Require Export Finite_sets.
Require Export FunctionProperties.
Set Asymmetric Patterns.
Inductive FiniteT : Type -> Prop :=
| empty_finite: FiniteT False
| add_finite: forall T:Type, FiniteT T -> FiniteT (option T)
| bij_finite: forall (X Y:Type) (f:X->Y), FiniteT X ->
invertible f -> FiniteT Y.

(* Specifications: *)
Lemma True_finite: FiniteT True.
Lemma finite_dec_exists: forall (X:Type) (P:X->Prop),
FiniteT X -> (forall x:X, {P x} + {~ P x}) ->
{ exists x:X, P x } + { forall x:X, ~ P x }.
Lemma finite_dec_forall: forall (X:Type) (P:X->Prop),
FiniteT X -> (forall x:X, { P x } + { ~ P x }) ->
{ forall x:X, P x } + { exists x:X, ~ P x }.
Lemma finite_eq_dec: forall X:Type, FiniteT X ->
forall x y:X, {x=y} + {x<>y}.
Lemma finite_dep_choice: forall (A:Type) (B:forall x:A, Type)
(R:forall x:A, B x->Prop),
FiniteT A -> (forall x:A, exists y:B x, R x y) ->
exists f:(forall x:A, B x), forall x:A, R x (f x).
Lemma finite_choice : forall (A B:Type) (R:A->B->Prop),
FiniteT A -> (forall x:A, exists y:B, R x y) ->
exists f:A->B, forall x:A, R x (f x).
Lemma Finite_ens_type: forall {X:Type} (S:Ensemble X),
Finite _ S -> FiniteT { x:X | In S x }.
Lemma FiniteT_img: forall (X Y:Type) (f:X->Y),
FiniteT X -> (forall y1 y2:Y, y1=y2 \/ y1<>y2) ->
Finite _ (Im Full_set f).
Lemma surj_finite: forall (X Y:Type) (f:X->Y),
FiniteT X -> surjective f ->
(forall y1 y2:Y, y1=y2 \/ y1<>y2) ->
FiniteT Y.
Lemma finite_subtype: forall (X:Type) (P:X->Prop),
FiniteT X -> (forall x:X, P x \/ ~ P x) ->
FiniteT {x:X | P x}.
Lemma inj_finite: forall (X Y:Type) (f:X->Y),
FiniteT Y -> FunctionProperties.injective f ->
(forall y:Y, (exists x:X, f x = y) \/
(~ exists x:X, f x = y)) ->
FiniteT X.
Lemma finite_inj_surj: forall (X:Type) (f:X->X),
FiniteT X -> injective f -> surjective f.
Lemma finite_surj_inj: forall (X:Type) (f:X->X),
FiniteT X -> surjective f -> FunctionProperties.injective f.
Lemma finite_sum: forall X Y:Type, FiniteT X -> FiniteT Y ->
FiniteT (X+Y).
Lemma finite_prod: forall (X Y:Type), FiniteT X -> FiniteT Y ->
FiniteT (X*Y).
Lemma finite_exp: forall X Y:Type, FiniteT X -> FiniteT Y ->
FiniteT (X->Y).
Lemma FiniteT_has_nat_cardinal: forall X:Type, FiniteT X ->
exists! n:nat, cardinal _ (@Full_set X) n.