Section enumerable_definitions.
Variable (X : Type).
(* enumerability of a Type *)
Definition type_enum := exists f : nat -> option X, forall x, exists n, Some x = f n.
Definition type_enum_t := { f : nat -> option X | forall x, exists n, Some x = f n }.
Definition list_enum := exists f : nat -> list X, forall x, exists n, In x (f n).
Definition list_enum_t := { f : nat -> list X | forall x, exists n, In x (f n) }.
(* of a predicate, definition 1 *)
Definition opt_enum P := exists f : nat -> option X, forall x, P x <-> exists n, Some x = f n.
Definition opt_enum_t P := { f : nat -> option X | forall x, P x <-> exists n, Some x = f n }.
(* of a predicate, definition 2 *)
Definition rec_enum P := exists (Q : nat -> X -> bool),
forall x, P x <-> exists n, Q n x = true.
Definition rec_enum_t P := { Q : nat -> X -> bool | forall x, P x <-> exists n, Q n x = true }.
(* An alternate characterization with Boolean decider  Fact rec_enum_t_alt P : rec_enum_t P ≋ { Q : nat -> X -> bool | forall x, P x <-> exists n, Q n x = true }.  Section list_enum_by_measure_fin_t.  Variable (m : X -> nat) (Hm : forall n, fin_t (fun x => m x < n)).  Theorem list_enum_by_measure_fin_t : list_enum_t.  End list_enum_by_measure_fin_t.  Section type_enum_t_by_measure.  Variable (m : X -> nat) (Hm : forall n, opt_enum_t (fun x => m x <= n)).  Theorem type_enum_t_by_measure : type_enum_t.  End type_enum_t_by_measure.  End enumerable_definitions.  Section enumerable.  Variable (X : Type) (Xdiscr : discrete X) (Xenum : type_enum X) (Xenum_t : type_enum_t X).  Implicit Type (P : X -> Prop).  (* On a discrete type, opt_enum implies rec_enum *)
Fact opt_enum_rec_enum_discrete P : opt_enum P -> rec_enum P.
Fact opt_enum_rec_enum_discrete_t P : opt_enum_t P -> rec_enum_t P.
(* On a enumerable type, rec_enum implies opt_enum *)
Fact rec_enum_opt_enum_type_enum P : rec_enum P -> opt_enum P.
Fact rec_enum_opt_enum_type_enum_t P : rec_enum_t P -> opt_enum_t P.
Hint Resolve opt_enum_rec_enum_discrete rec_enum_opt_enum_type_enum
opt_enum_rec_enum_discrete_t rec_enum_opt_enum_type_enum_t : core.
(* On a datatype, opt_enum and rec_enum are equivalent *)

Theorem opt_rec_enum_equiv P : opt_enum P <-> rec_enum P.