# Computational Back-and-Forth Arguments

Set Implicit Arguments.
Unset Strict Implicit.
Open Scope type.

Require Import Lia List.

Notation "x 'el' L" := (In x L) (at level 70).
Notation "x 'nel' L" := (~ In x L) (at level 70).
Notation "L '<<=' L'" := (incl L L') (at level 70).

Notation pi1 := proj1_sig.
Notation pi2 := proj2_sig.

## Preliminary Definitions

(* Retracts of nat *)

Class retract X Y :=
{
I : X -> Y;
R : Y -> X;
HIR : forall x, R (I x) = x;
}.

Definition discrete X :=
forall (x y : X), { x = y } + { x <> y }.

Existing Class discrete.

Local Instance retract_discrete X Y :
retract X Y -> discrete Y -> discrete X.
Proof.
intros r d x x'. destruct (d (I x) (I x')) as [H|H].
- left. enough (Some x = Some x') by congruence. rewrite <- (HIR x), <- (HIR x'). now rewrite H.
- right. intros Hx. apply H. now rewrite Hx.
Qed.

Local Instance countable_discrete X :
retract X nat -> discrete X.
Proof.
intros r. eapply retract_discrete; try apply r. intros n n'. decide equality.
Qed.

Lemma discrete_indec X (x : X) (L : list X) :
discrete X -> { x el L } + { x nel L }.
Proof.
intros H. induction L; cbn.
- now right.
- destruct (H a x) as [H1|H1]; auto.
destruct (IHL) as [H2|H2]; auto.
right. tauto.
Qed.

(* Finite functions implemented as lists *)

Definition table X Y := list (X * Y).

Notation dom f :=
(map fst f).

Notation ran f :=
(map snd f).

Lemma dom_el X Y (f : table X Y) a b :
(a, b) el f -> a el dom f.
Proof.
intros H. apply in_map_iff. now exists (a, b).
Qed.

Lemma ran_el X Y (f : table X Y) a b :
(a, b) el f -> b el ran f.
Proof.
intros H. apply in_map_iff. now exists (a, b).
Qed.

Local Hint Resolve dom_el ran_el : core.

Fixpoint im X Y {X_dec : discrete X} (f : table X Y) a : option Y :=
match f with
| nil => None
| (c, d)::f => if X_dec a c then Some d else im f a
end.

Lemma im_some X Y {X_dec : discrete X} (f : table X Y) a b :
im f a = Some b -> (a, b) el f.
Proof.
induction f as [|[c d] f IH]; cbn; try congruence.
destruct X_dec as [H|H]; subst.
- intros [=]; subst. now left.
- intros H'. right. now apply IH.
Qed.

Lemma im_none X Y {X_dec : discrete X} (f : table X Y) a :
im f a = None -> a nel dom f.
Proof.
induction f as [|[c d] f IH]; cbn; try congruence.
destruct X_dec as [H|H]; subst.
- congruence.
- firstorder.
Qed.

Notation flip f :=
(map (fun p => (snd p, fst p)) f).

Lemma flip_el X Y (f : table X Y) x y :
(x, y) el f <-> (y, x) el flip f.
Proof.
induction f as [|[x' y']]; cbn; try tauto. split.
- rewrite IHf. intuition. left. congruence.
- rewrite IHf. intuition. left. congruence.
Qed.

Lemma double_flip X Y (f : table X Y) :
flip (flip f) = f.
Proof.
induction f; cbn; intuition; cbn; congruence.
Qed.

## Abstract Back-and-Forth Argument

Section Abstract.

(* Assumptions regarding the invertable abstract structure A *)
Variable structure : Type -> Type -> Type.
Variable srev : forall {X Y}, structure X Y -> structure Y X.
Hypothesis srev_invol : forall {X Y} {S : structure X Y}, srev (srev S) = S.

(* Assumptions regarding the abstract isomorphism property ~ *)
Variable iso : forall {X Y}, structure X Y -> X -> X -> Y -> Y -> Prop.
Hypothesis iso_eq : forall {X Y} {S : structure X Y} x x' y y', iso S x x' y y' -> (x = x' <-> y = y').
Hypothesis iso_rev : forall {X Y} {S : structure X Y} x x' y y', iso S x x' y y' -> iso (srev S) y y' x x'.

Definition tiso X Y (S : structure X Y) (f : table X Y) :=
forall x x' y y', (x, y) el f -> (x', y') el f -> iso S x x' y y'.

(* Assumptions regarding the one-step extension function mu *)
Variable find : forall {X Y}, structure X Y -> X -> table X Y -> Y.
Hypothesis find_iso : forall {X Y} {S : structure X Y} f x, x nel dom f -> tiso S f -> tiso S ((x, find S x f) :: f).

(* Definition of the refined extension function mu' *)

Definition step X Y {RX : retract X nat} (S : structure X Y) x (f : table X Y) : table X Y :=
(x, match im f x with Some b => b | None => find S x f end) :: f.

Lemma incl_tiso X Y (S : structure X Y) (f f' : table X Y) :
tiso S f -> f' <<= f -> tiso S f'.
Proof.
unfold tiso. intuition.
Qed.

Lemma step_tiso X Y {RX : retract X nat} (S : structure X Y) (f : table X Y) n :
tiso S f -> tiso S (step S n f).
Proof.
intros H. unfold step.
destruct im as [y|] eqn : Hy.
- eapply incl_tiso; try apply H. apply im_some in Hy. intuition.
- apply im_none in Hy. now apply find_iso.
Qed.

Lemma flip_tiso X Y (S : structure X Y) f :
tiso S f -> tiso (srev S) (flip f).
Proof.
intros Hf x x' y y' H1 H2. apply iso_rev.
apply Hf; try now apply flip_el.
Qed.

(* Fix countable X and Y related by a structure SXY *)

Variable X Y : Type.
Variable SXY : structure X Y.

Variable RX : retract X nat.
Variable RY : retract Y nat.

(* Construction and verification of stages L_n *)

Fixpoint L (n : nat) : table X Y :=
match n with
| 0 => nil
| S n => flip (step (srev SXY) (R n) (flip (step SXY (R n) (L n))))
end.

Lemma L_tiso n :
tiso SXY (L n).
Proof.
induction n.
- intros x x' y y' [].
- rewrite <- srev_invol at 1. unfold L; fold L.
eapply flip_tiso, step_tiso, flip_tiso, step_tiso, IHn.
Qed.

(* Construction and verification of isomorphism F(orth) *)

Lemma L_tot x :
{ y | (x, y) el L (S (I x)) }.
Proof.
eexists. right. left. rewrite HIR. reflexivity.
Qed.

Lemma L_sur y :
{ x | (x, y) el L (S (I y)) }.
Proof.
eexists; cbn; rewrite HIR. now left.
Qed.

Definition Forth x :=
pi1 (L_tot x).

Definition Back y :=
pi1 (L_sur y).

Lemma L_cum n k :
n <= k -> L n <<= L k.
Proof.
induction 1.
- intuition.
- cbn. rewrite double_flip; intuition.
Qed.

Lemma L_iso n x y n' x' y' :
(x, y) el L n -> (x', y') el L n' -> iso SXY x x' y y' /\ iso SXY x' x y' y.
Proof.
intros H1 H2. split; apply (@L_tiso (n + n')).
all: eapply L_cum; try eassumption; lia.
Qed.

Lemma forth_iso x x' :
iso SXY x x' (Forth x) (Forth x').
Proof.
unfold Forth.
destruct (L_tot x) as [y H1], (L_tot x') as [y' H2]; cbn.
eapply L_iso; eassumption.
Qed.

Lemma back_forth x :
Back (Forth x) = x.
Proof.
unfold Forth, Back.
destruct L_tot as [y H1], L_sur as [x' H2]; cbn -[L] in *.
apply (@iso_eq _ _ SXY x' x y y); trivial.
eapply L_iso; eassumption.
Qed.

Lemma forth_back y :
Forth (Back y) = y.
Proof.
unfold Forth, Back.
destruct L_sur as [x H1], L_tot as [y' H2]; cbn -[L] in *.
apply (@iso_eq _ _ SXY x x y' y); trivial.
eapply L_iso; eassumption.
Qed.

Definition inverse (F : X -> Y) (G : Y -> X) :=
(forall x, G (F x) = x) /\ (forall y, F (G y) = y).

Theorem back_and_forth :
{ F & { G | inverse F G /\ forall x x', iso SXY x x' (F x) (F x') } }.
Proof.
exists Forth, Back.
split; try apply forth_iso.
split; try apply back_forth.
apply forth_back.
Qed.

End Abstract.

## Cantor's Isomorphism Theorem

(* Definition of unbounded dense linear orders *)

Class dulo X :=
{
point : X;
rel : X -> X -> Prop;
rel_irref : forall x, ~ rel x x;
rel_trans : forall x y z, rel x y -> rel y z -> rel x z;
rel_trich : forall x y, { rel x y } + { x = y } + { rel y x };
rel_up : forall x, { y | rel x y };
rel_down : forall x, { y | rel y x };
rel_dense : forall x y, rel x y -> { z | rel x z /\ rel z y };
}.

Arguments rel {_ _} _ _, {_} _ _ _.

Lemma rel_asym X (OX : dulo X) :
forall x y, rel OX x y -> ~ rel OX y x.
Proof.
intros x y H1 H2. apply (@rel_irref X OX x).
eapply rel_trans; eauto.
Qed.

(* Note that in contrast to the paper we assume an informative proof rel_trich for trichotomy,
sparing the additional assumption of a decider for the relation rel and equality eq *)

Lemma rel_dec X (OX : dulo X) :
forall x y, { rel OX x y } + { ~ rel OX x y }.
Proof.
intros x y. destruct (rel_trich x y) as [[H|H]|H].
- left. apply H.
- right. rewrite H. apply rel_irref.
- right. intros H'. eapply rel_asym; eauto.
Qed.

Lemma dulo_disc X (OX : dulo X) :
discrete X.
Proof.
intros x y. destruct (rel_trich x y) as [[H|H]|H].
- right. intros ->. now apply rel_irref in H.
- now left.
- right. intros ->. now apply rel_irref in H.
Qed.

(* This section establishes the extension function for Cantor (Definition 4 and Lemma 5) *)

Section CantorStep.

Variables A B : Type.

Context (OA : dulo A) (OB : dulo B).

Notation "a <A a'" := (rel OA a a') (at level 70).
Notation "b <B b'" := (rel OB b b') (at level 70).

Hint Resolve rel_trans : core.

Definition morph' f :=
forall a c b d, (a, b) el f -> (c, d) el f -> a <A c <-> b <B d.

Definition matches f a b :=
forall c d, (c, d) el f -> a <A c <-> b <B d.

Lemma matches_down f a b c d :
a nel dom f -> b nel ran f -> matches f a b -> (c, d) el f -> c <A a <-> d <B b.
Proof.
intros Ha Hb Hf H1. split; intros H2.
- destruct (rel_trich d b) as [[H|<-]|H]; trivial.
+ contradict Hb. apply (ran_el H1).
+ apply (Hf c) in H; trivial. contradiction (rel_asym H H2).
- destruct (rel_trich c a) as [[H|<-]|H]; trivial.
+ contradict Ha. apply (dom_el H1).
+ apply (Hf c d) in H; trivial. contradiction (rel_asym H H2).
Qed.

Definition min_im f a :
{ min | (exists a', (a', min) el f /\ a <A a') /\ forall c d, (c, d) el f -> d <B min -> ~ a <A c }
+ { forall c d, (c, d) el f -> ~ a <A c }.
Proof.
induction f as [|[u v] f IH].
- right. intros c d [].
- destruct IH as [[min[H1 H2]]|H], (rel_dec OA a u) as [Ha|Ha].
+ destruct (rel_dec OB v min) as [Hv|Hv].
* left. exists v. split; try firstorder 0.
intros c d [[=]|H'] Hd; subst; eauto.
now apply rel_irref in Hd.
* left. firstorder congruence.
+ left. exists min. firstorder congruence.
+ left. exists v. split; try firstorder 0.
intros c d [[=]|H']; subst; eauto.
intros [] % rel_irref.
+ right. firstorder congruence.
Qed.

Definition max_im f a :
{ max | (exists a', (a', max) el f /\ a' <A a) /\ forall c d, (c, d) el f -> max <B d -> ~ c <A a }
+ { forall c d, (c, d) el f -> ~ c <A a }.
Proof.
induction f as [|[u v] f IH].
- right. intros c d [].
- destruct IH as [[max[H1 H2]]|H], (rel_dec OA u a) as [Ha|Ha].
+ destruct (rel_dec OB max v) as [Hv|Hv].
* left. exists v. split; try firstorder 0.
intros c d [[=]|H'] Hd; subst; eauto.
now apply rel_irref in Hd.
* left. firstorder congruence.
+ left. exists max. firstorder congruence.
+ left. exists v. split; try firstorder 0.
intros c d [[=]|H']; subst; eauto.
intros [] % rel_irref.
+ right. firstorder congruence.
Qed.

(* Definition and verification of mu_C *)

Definition partner a f :=
match min_im f a, max_im f a with
| inleft (exist _ min H1), inleft (exist _ max H2)
=> match rel_dec OB max min with left h => pi1 (@rel_dense _ OB max min h) | _ => @point _ OB end
| inleft (exist _ min _), _ => pi1 (@rel_down _ OB min)
| _, inleft (exist _ max _) => pi1 (@rel_up _ OB max)
| _, _ => @point _ OB
end.

Lemma partner_ran f a :
a nel dom f -> morph' f -> partner a f nel ran f.
Proof.
intros Ha Hf. unfold partner; destruct min_im as [[min H1]|H1], max_im as [[max H2]|H2].
try destruct rel_dec as [H|H]. all: intros [[c d][Heq H']] % in_map_iff; cbn in *; subst.
- destruct rel_dense as [x[H3 H4]]; cbn in *.
destruct (rel_trich a c) as [[|<-]|]; intuition eauto.
- destruct H1 as [[a1 Ha1]H1], H2 as [[a2 Ha2]H2].
apply H. apply (Hf a2 a1 max); try tauto. apply rel_trans with a; tauto.
- destruct rel_down as [x Hx]; cbn in *.
destruct (rel_trich a c) as [[|<-]|]; intuition eauto.
- edestruct rel_up as [x Hx]; cbn in *.
destruct (rel_trich a c) as [[|<-]|]; intuition eauto.
- apply Ha. apply dom_el with (@point _ OB).
destruct (rel_trich a c) as [[|<-]|]; trivial; exfalso; intuition eauto.
Qed.

Lemma partner_matches f a :
a nel dom f -> morph' f -> matches f a (partner a f).
Proof.
intros Ha Hf c d Hc. unfold partner.
destruct min_im as [[min[[u Hu]H1]]|H1], max_im as [[max[[v Hv]H2]]|H2].
- assert (Hm : max <B min). { eapply Hf; intuition eauto. }
destruct rel_dec as [H|H]; try tauto. destruct rel_dense as [x[H3 H4]]; cbn. clear H. split; intros H.
+ destruct (rel_trich x d) as [[|<-]|]; trivial; exfalso; intuition eauto.
+ destruct (rel_trich a c) as [[|<-]|]; trivial; exfalso; intuition eauto.
- destruct rel_down as [x Hx]; cbn in *. split; intros H.
+ destruct (rel_trich x d) as [[|<-]|]; trivial; exfalso; intuition eauto.
+ destruct (rel_trich a c) as [[|<-]|]; trivial; exfalso; intuition eauto.
- destruct rel_up as [x Hx]; cbn in *. split; intros H.
+ destruct (rel_trich x d) as [[|<-]|]; trivial; exfalso; intuition eauto.
+ destruct (rel_trich a c) as [[|<-]|]; trivial; exfalso; intuition eauto.
- assert (a = c) as <-.
+ destruct (rel_trich a c) as [[]|]; firstorder.
+ exfalso. intuition eauto.
Qed.

Lemma step_morph' f x :
x nel dom f -> morph' f -> morph' ((x, partner x f) :: f).
Proof.
intros Hx Hf a b c d [[=]|H] [[=]|H']; subst.
- split; now intros H % rel_irref.
- apply partner_matches; trivial.
- apply matches_down with f; trivial.
+ eapply partner_ran; trivial.
+ apply partner_matches; trivial.
- now apply Hf.
Qed.

Definition morph f :=
forall a c b d, (a, b) el f -> (c, d) el f -> ((a = c) <-> (b = d)) /\ (a <A c <-> b <B d).

Lemma morph_morph' f :
morph f -> morph' f.
Proof.
intros Hf. intros x y u v H1 H2. now apply Hf.
Qed.

Lemma step_morph f x :
x nel dom f -> morph f -> morph ((x, partner x f) :: f).
Proof.
intros Hx Hf a b c d [[=]|H] [[=]|H']; subst.
- split; try tauto. split; now intros H % rel_irref.
- split.
+ split; intros Heq; subst; try now apply dom_el in H'.
apply ran_el in H'. apply partner_ran in H'; try tauto.
now apply morph_morph'.
+ apply partner_matches; trivial. now apply morph_morph'.
- split.
+ split; intros Heq; subst; try now apply dom_el in H.
apply ran_el in H. apply partner_ran in H; try tauto.
now apply morph_morph'.
+ apply matches_down with f; trivial.
* eapply partner_ran; trivial. now apply morph_morph'.
* apply partner_matches; trivial. now apply morph_morph'.
- now apply Hf.
Qed.

End CantorStep.

(* Instantiation to Cantor's isomorphism theorem *)

Notation "x < y" := (rel x y).

Theorem Cantor X Y (OX : dulo X) (OY : dulo Y) (RX : retract X nat) (RY : retract Y nat) :
{ F : X -> Y & { G | inverse F G /\ forall x x', x < x' <-> (F x) < (F x') } }.
Proof.
unshelve edestruct back_and_forth as [F[G[H1 H2]]].
- intros A B. exact (dulo A * dulo B). (* structure *)
- intros A B [OA OB]. exact (OB, OA). (* srev *)
- intros A B [OA OB] a a' b b'. exact ((a = a' <-> b = b') /\ (a < a' <-> b < b')). (* iso *)
- cbn. intros A B [OA OB] f a. exact (partner OA OB f a). (* find *)
- exact X.
- exact Y.
- exact (OX, OY).
- intros A B [OA OB]. reflexivity. (* srev_invol *)
- cbn. tauto. (* iso_eq *)
- cbn. tauto. (* iso_rev *)
- cbn. intros A B [OA OB] f x. unfold step, tiso. now apply step_morph. (* find_iso *)
- exact RX.
- exact RY.
- cbn in *. exists F, G. split; try apply H1. apply H2.
Qed.

Print Assumptions Cantor. (* Closed under the global context *)

## Myhills's Isomorphism Theorem

(* Import of the Equations package to support definition by well-founded recursion *)

From Equations Require Import Equations.
Unset Equations With Funext.

(* Definition of one-one interreducible predicates *)

Definition inj X Y (f : X -> Y) :=
forall x x', f x = f x' -> x = x'.

Definition reduction X Y (p : X -> Prop) (q : Y -> Prop) f :=
forall x, p x <-> q (f x).

Class bireduction X Y :=
{
eX : discrete X;
eY : discrete Y;
p : X -> Prop;
q : Y -> Prop;
f : X -> Y;
g : Y -> X;
f_inj : inj f;
g_inj : inj g;
f_red : reduction p q f;
g_red : reduction q p g;
}.

(* This section establishes the extension function for Myhill (Definition 8 and Lemma 9),
adapted from https://github.com/synthetic-reducibility-coq/paper/blob/main/Synthetic/myhill.v *)

Section MyhillStep.

Variables (X Y : Type).

Variable p : X -> Prop.
Variable q : Y -> Prop.

Variable f : X -> Y.
Hypothesis inj_f : inj f.
Hypothesis f_red : reduction p q f.

Variable eX : discrete X.
Variable eY : discrete Y.

Lemma ran_compute (y : Y) (L : table X Y) :
y el ran L -> {x : X | (x, y) el L}.
Proof.
induction L as [ | [x y'] L IH] in y |- *.
- inversion 1.
- cbn. destruct (eY y' y) as [-> | He].
+ exists x. eauto.
+ intros H. destruct (IH y) as (x' & IHx').
firstorder. exists x'. eauto.
Qed.

Lemma discrete_prod :
discrete (X * Y).
Proof.
intros [x y] [x' y']. destruct (eX x x'), (eY y y'); subst; try now left. all: right; congruence.
Qed.

(* Definition and verification of mu_C *)

Equations gamma (x : X) (C : table X Y) : X by wf (length C) lt :=
gamma x C with discrete_indec (f x) (ran C) eY => {
| left H with ran_compute H => {
| exist _ x' H' := gamma x' (remove discrete_prod (x', f x) C)
};
| right _ := x
}.
Next Obligation.
abstract (apply remove_length_lt; eauto).
Qed.

Definition mstep x C :=
f (gamma x C).

Arguments remove {_ _} _ _.

Definition correspondence (C : table X Y) :=
forall x x' y y', (x, y) el C -> (x', y') el C -> (x = x' <-> y = y') /\ (p x <-> q y).

Lemma correspondence_remove C x y :
correspondence C -> correspondence (@remove _ discrete_prod (x, y) C).
Proof.
intros HC. split. 1: split.
- intros <-. eapply HC; try reflexivity; eapply in_remove; eauto.
- intros <-. eapply HC; try reflexivity; eapply in_remove; eauto.
- eapply HC; eapply in_remove; eauto.
Qed.

Lemma gamma_spec (C : table X Y) x :
x nel dom C -> correspondence C -> (p x <-> p (gamma x C)) /\ (gamma x C) el (x :: dom C) /\ (mstep x C) nel ran C.
Proof.
intros Hx HC.
funelim (gamma x C); try rename H into IH; unfold mstep in *.
- rewrite <- Heqcall. cbn. intuition.
- specialize H0 as (IH1 & IH2 & IH3).
{ intros ([] & E & [] % in_remove) % in_map_iff; cbn in E; subst.
apply H0. f_equal. eapply HC; eauto. }
{ eapply correspondence_remove; eauto. }
split. 2: split.
+ etransitivity. eapply f_red. rewrite <- Heqcall. rewrite <- IH1. symmetry. eapply HC; eauto.
+ rewrite <- Heqcall. specialize IH2 as [EE | ([] & E & [] % in_remove) % in_map_iff]; eauto.
* rewrite <- EE. right. eauto.
* rewrite <- E. right. eauto.
+ rewrite Heqcall in IH3, IH2, IH1.
intros ([] & E & ?) % (in_map_iff). cbn in E. subst.
eapply IH3. eapply in_map_iff.
eexists (x0, _). split. cbn. reflexivity.
eapply in_in_remove. 2: exact H.
intros [= -> E % inj_f]. apply Hx. rewrite E in IH2.
specialize IH2 as [-> | ([] & EE & [] % in_remove) % in_map_iff]; cbn in *; subst; eauto.
Qed.

Lemma step_corr C x :
x nel dom C -> correspondence C -> correspondence ((x, mstep x C) :: C).
Proof.
intros Hx HC. split. 1: split.
- intros <-. destruct H as [[= <- <-] | ], H0 as [[= <-] | ]; eauto. 3: eapply HC; eauto.
+ exfalso. apply Hx. eauto.
+ exfalso. apply Hx. eauto.
- intros <-. destruct H as [[= <- <-] | ], H0 as [[= <-] | ]; eauto. 3: eapply HC; eauto.
+ exfalso. eapply gamma_spec; eauto.
+ subst. exfalso. eapply gamma_spec; eauto.
- destruct H as [[= <- <-] | ].
+ etransitivity. eapply gamma_spec; eauto. eapply f_red.
+ eapply HC; eauto.
Qed.

End MyhillStep.

(* Instantiation to Myhill's isomorphism theorem *)

Theorem Myhill X Y (SXY : bireduction X Y) (RX : retract X nat) (RY : retract Y nat) :
{ F : X -> Y & { G | inverse F G /\ reduction p q F } }.
Proof.
unshelve edestruct back_and_forth as [F[G[H1 H2]]].
- intros A B. exact (bireduction A B). (* structure *)
- intros A B S. cbn in *. apply (@Build_bireduction B A eY eX q p g f); apply S. (* srev *)
- intros A B S a a' b b'. cbn in S. exact ((a = a' <-> b = b') /\ (p a <-> q b)). (* iso *)
- cbn. intros A B S C a. exact (mstep f eX eY C a). (* find *)
- exact X.
- exact Y.
- exact SXY.
- cbn. intros A B []. reflexivity. (* srev_invol *)
- cbn. tauto. (* iso_eq *)
- cbn. tauto. (* iso_rev *)
- cbn. intros A B S C a. unfold step, tiso. apply step_corr; apply S. (* find_iso *)
- exact RX.
- exact RY.
- cbn in *. exists F, G. split; try apply H1. intros x. now apply H2.
Qed.

Print Assumptions Myhill. (* Closed under the global context *)

Theorem Cantor_Bernstein X Y (RX : retract X nat) (RY : retract Y nat) (f : X -> Y) (g : Y -> X) :
inj f -> inj g -> { F : X -> Y & { G | inverse F G } }.
Proof.
intros Hf Hg.
assert (SXY : bireduction X Y).
- unshelve esplit.
+ exact (fun _ => False).
+ exact (fun _ => False).
+ exact f.
+ exact g.
+ exact _.
+ exact _.
+ exact Hf.
+ exact Hg.
+ intros x. tauto.
+ intros x. tauto.
- destruct (Myhill SXY) as [F[G HFG]]; trivial.
exists F, G. apply HFG.
Qed.