(* ** Definitions *)

Definition compl X p := fun x : X => ~ p x.Definition decidable {X} (p : X -> Prop) := exists f, forall x, p x <-> f x = true.Definition enumerable {X} (p : X -> Prop) := exists f, forall x, p x <-> exists n : nat, f n = Some x.Definition discrete X := decidable (fun '(x,y) => x = y :> X).Definition enumerable__T X := exists f : nat -> option X, forall x, exists n, f n = Some x.

(* Specifications: *)
Lemma dec_decidable' X p : (forall x : X, dec (p x)) -> { f : _ | forall x, p x <-> f x = true}.
Lemma decidable_iff X p : decidable p <-> inhabited (forall x : X, dec (p x)).
Lemma discrete_iff X : discrete X <-> inhabited (eq_dec X).
Lemma dec_compl X p : decidable p -> decidable (fun x : X => ~ p x).
Lemma dec_conj X p q : decidable p -> decidable q -> decidable (fun x : X => p x /\ q x).
Lemma dec_disj X p q : decidable p -> decidable q -> decidable (fun x : X => p x \/ q x).
Theorem dec_count_enum X (p : X -> Prop) : decidable p -> enumerable__T X -> enumerable p.
Theorem dec_count_enum' X (p : X -> Prop) : decidable p -> enumerable__T X -> enumerable (fun x => ~ p x).
Lemma enumerable_enumerable_T X : enumerable (fun _ : X => True) <-> enumerable__T X.