Section L_enum_rec.
Variable X : Type.
Context `{registered X}.
Variable (p : X -> Prop).
Hypotheses (f : nat -> option X) (c_f : computable f) (H_f : enumerates f p).
Hypotheses (d : X -> X -> bool) (c_d : computable d) (H_d : forall x y, reflect (x = y) (d x y)).
Definition test := (fun x n => match f n with Some y => d x y | None => false end).
Instance term_test : computable test.
End L_enum_rec.
Definition opt_to_list n := match nat_enum n with Some x => [x] | None => [] end.
Instance term_opt_to_list : computable opt_to_list.
Definition L_nat := cumul (opt_to_list).
Instance term_L_nat : computable L_nat.
(* Definition T_nat_nat := Eval cbn in L_T (X := nat * nat). *)
(* Definition pair' : nat * nat -> nat * nat := fun '(x,y) => (x,y). *)
(* Instance term_pair' : computable pair'. *)
(* Proof. *)
(*   extract. *)
(* Qed. *)
(* Instance term_nat_rec {X : Set} `{registered X} : computable (@nat_rec (fun _ => X)). *)
(* Proof. *)
(*   unfold nat_rec, nat_rect. extract. *)
(* Qed. *)
Definition F' := (fix F (n : nat) : nat := match n with
| 0 => 0
| S n0 => S n0 + F n0
end).
Instance term_F' : computable F'.
Definition F'' := (fix F (n0 : nat) : nat * nat := match n0 with
| 0 => (0, 0)
| S n1 => match F n1 with
| (0, y) => (S y, 0)
| (S x0, y) => (x0, S y)
end
end).
Instance term_F'' : computable F''.
Instance term_embed_nat : computable embed.
Instance term_unembed_nat : computable unembed.
(* Definition F''' := (prod_enum nat_enum nat_enum). *)
(* Instance term_prod_enum : computable F'''. *)
(* Proof. *)
(*   unfold F'''. *)
(*   extract. *)
(* Qed. *)
(* Instance term_nat_enum : computable nat_enum. *)
(* Proof. *)
(*   extract. *)
(* Qed. *)
(* Instance term_T_nat_nat : computable T_nat_nat. *)
(* Proof. *)
(*   change (computable *)
(*     (fix f (n : nat) : list (nat * nat) := match n with *)
(*                                            | 0 => [] *)
(*                                            | S n0 => f n0 ++ opt_to_list (F''' n0) *)
(*                                            end)). *)
(*   extract. *)
(* Qed. *)
(* Instance term_R_nat_nat : computable R_nat_nat. *)
(* Proof. *)
(*   change (computable (fun n : nat => nthe n (T_nat_nat n))). *)
(*   extract. *)
(* Qed. *)
(* Instance term_ofNat X `{registered X} : *)
(*   computable (@ofNat X). *)
(* Proof. *)
(*   extract. *)
(* Qed. *)
Definition lenumerates {X} L (p : X -> Prop) :=
cumulative L /\ (forall x : X, p x <-> (exists m : nat, x el L m)).
Definition L_enum {X} `{registered X} (p : X -> Prop) :=
exists L, is_computable L /\ lenumerates L p.

Lemma projection X Y {HX : registered X} {HY : registered Y} (p : X * Y -> Prop) :
L_enumerable p -> L_enumerable (fun x => exists y, p (x,y)).