(************************************************************************)
(*         *   The Coq Proof Assistant / The Coq Development Team       *)
(*  v      *   INRIA, CNRS and contributors - Copyright 1999-2018       *)
(* <O___,, *       (see CREDITS file for the list of authors)           *)
(*   \VV/  **************************************************************)
(*    //   *    This file is distributed under the terms of the         *)
(*         *     GNU Lesser General Public License Version 2.1          *)
(*         *     (see LICENSE file for the text of the license)         *)
(************************************************************************)
(** * Functions on finite domains *)
(** Main result : for functions [f:A->A] with finite [A], f injective <-> f bijective <-> f surjective. *)
Set Implicit Arguments.
(** General definitions *)
Definition Injective {A B} (f : A->B) :=
forall x y, f x = f y -> x = y.
Definition Surjective {A B} (f : A->B) :=
forall y, exists x, f x = y.
Definition Bijective {A B} (f : A->B) :=
exists g:B->A, (forall x, g (f x) = x) /\ (forall y, f (g y) = y).
(** Finiteness is defined here via exhaustive list enumeration *)
Definition Full {A:Type} (l:list A) := forall a:A, In a l.
Definition Finite (A:Type) := exists (l:list A), Full l.
(** In many following proofs, it will be convenient to have list enumerations without duplicates. As soon as we have decidability of equality (in Prop), this is equivalent to the previous notion. *)
Definition Listing {A:Type} (l:list A) := NoDup l /\ Full l.
Definition Finite' (A:Type) := exists (l:list A), Listing l.
(** Injections characterized in term of lists *)
(** Surjection characterized in term of lists *)
(** Main result : *)
(** An injective and surjective function is bijective. We need here stronger hypothesis : decidability of equality in Type. *)
Definition EqDec (A:Type) := forall x y:A, {x=y}+{x<>y}.
(** First, we show that a surjective f has an inverse function g such that f.g = id. *)
(* NB: instead of (Finite A), we could ask for (RecEnum A) with: Definition RecEnum A := exists h:nat->A, surjective h. *)

Lemma Finite_Empty_or_not A :
Finite A -> (A->False) \/ exists a:A,True.