Library ZFrelations


Require Import ZFpairs.

Relations


Definition is_relation x :=
   p, p x -> p == couple (fst p) (snd p).

Definition rel_app r x y := couple x y r.

Instance rel_app_morph :
  Proper (eq_set ==> eq_set ==> eq_set ==> iff) rel_app.
unfold rel_app; do 4 red; intros.
rewrite H; rewrite H0; rewrite H1; reflexivity.
Qed.

Definition rel_domain r :=
  subset (union (union r)) (fun x => exists y, rel_app r x y).

Definition rel_image r :=
  subset (union (union r)) (fun y => exists x, rel_app r x y).

Instance rel_image_morph : morph1 rel_image.
do 2 red; intros.
unfold rel_image in |- *.
apply subset_morph.
 rewrite H; reflexivity.

 split; intros.
  destruct H1.
  exists x1.
  rewrite <- H; trivial.

  destruct H1.
  exists x1.
  rewrite H; trivial.
Qed.

Lemma rel_image_ex : r x, x rel_domain r -> exists y, rel_app r x y.
Proof.
unfold rel_domain; intros.
elim subset_elim2 with (1:=H); intros.
destruct H1.
rewrite <- H0 in H1.
exists x1; trivial.
Qed.

Lemma rel_domain_intro : r x y, rel_app r x y -> x rel_domain r.
Proof.
unfold rel_domain in |- *; intros.
apply subset_intro.
 red in H.
   apply union_intro with (pair x y); auto.
   apply union_intro with (couple x y); trivial.
   unfold couple in |- *; auto.
 exists y; trivial.
Qed.

Lemma rel_image_intro : r x y, rel_app r x y -> y rel_image r.
Proof.
unfold rel_image in |- *; intros.
apply subset_intro.
 red in H.
   apply union_intro with (pair x y); auto.
   apply union_intro with (couple x y); trivial.
   unfold couple in |- *; auto.
 exists x; trivial.
Qed.

Definition rel_comp f g :=
  subset (prodcart (rel_domain g) (rel_image f))
    (fun p => exists2 y, rel_app g (fst p) y & rel_app f y (snd p)).

Lemma rel_comp_intro : f g x y z,
  rel_app g x y -> rel_app f y z -> rel_app (rel_comp f g) x z.
Proof.
intros.
red in |- *.
unfold rel_comp in |- *.
apply subset_intro.
 apply couple_intro.
  apply rel_domain_intro with (1 := H).
  apply rel_image_intro with (1 := H0).
 exists y.
   rewrite fst_def.
    trivial.
   rewrite snd_def; trivial.
Qed.

Relation typing

Definition rel A B := power (prodcart A B).

Lemma rel_mono :
  Proper (incl_set ==> incl_set ==> incl_set) rel.
unfold rel; do 3 red; intros.
apply power_mono.
apply prodcart_mono; trivial.
Qed.

Instance rel_morph : morph2 rel.
Proof.
do 3 red; intros.
unfold rel.
rewrite H; rewrite H0; reflexivity.
Qed.

Lemma app_typ1 : r x y A B, r rel A B -> rel_app r x y -> x A.
Proof.
unfold rel, rel_app in |- *; intros.
specialize power_elim with (1 := H) (2 := H0); intro.
rewrite <- (fst_def x y).
apply fst_typ with (1 := H1).
Qed.

Lemma app_typ2 : r x y A B, r rel A B -> rel_app r x y -> y B.
Proof.
unfold rel, rel_app in |- *; intros.
specialize power_elim with (1 := H) (2 := H0); intro.
rewrite <- (snd_def x y).
apply snd_typ with (1 := H1).
Qed.

Lemma rel_is_relation : f A B, f rel A B -> is_relation f.
Proof.
unfold rel in |- *; red in |- *; intros.
specialize power_elim with (1 := H) (2 := H0); apply surj_pair.
Qed.

Lemma rel_domain_incl : r A B, r rel A B -> rel_domain r A.
Proof.
unfold rel_domain in |- *; intros.
red in |- *; intros.
elim subset_elim2 with (1 := H0); intros.
destruct H2 as (y, img_z).
rewrite <- H1 in img_z.
apply app_typ1 with (1 := H) (2 := img_z).
Qed.

Lemma rel_image_incl : r A B, r rel A B -> rel_image r B.
Proof.
unfold rel_image in |- *; intros.
red in |- *; intros.
elim subset_elim2 with (1 := H0); intros.
destruct H2 as (x0, img_z).
rewrite <- H1 in img_z.
apply app_typ2 with (1 := H) (2 := img_z).
Qed.

Lemma relation_is_rel :
   r A B,
  is_relation r ->
  rel_domain r A ->
  rel_image r B ->
  r rel A B.
Proof.
unfold rel in |- *; intros.
red in H.
apply power_intro; intros.
 rewrite (H _ H2).
apply couple_intro.
 apply H0.
   apply rel_domain_intro with (snd z).
   red in |- *.
    rewrite <- (H _ H2); trivial.
 apply H1.
   apply rel_image_intro with (fst z).
   red in |- *.
    rewrite <- (H _ H2); trivial.
Qed.

Definition inject_rel R A B :=
  subset (prodcart A B) (fun p => R (fst p) (snd p)).

Lemma inject_rel_is_rel : (R:set->set->Prop) A B,
  inject_rel R A B rel A B.
Proof.
unfold rel in |- *.
intros.
apply power_intro; intros.
unfold inject_rel in H.
apply subset_elim1 with (1 := H).
Qed.

Lemma inject_rel_intro :
   (R:set->set->Prop) A B x y,
  ext_rel A R ->
  x A ->
  y B ->
  R x y ->
  rel_app (inject_rel R A B) x y.
Proof.
unfold inject_rel, rel_app in |- *; intros.
apply subset_intro.
 apply couple_intro; trivial.
 elim (H x (fst (couple x y)) y (snd (couple x y))); intros; auto.
   rewrite fst_def; reflexivity.
   rewrite snd_def; reflexivity.
Qed.

Lemma inject_rel_elim :
   (R:set->set->Prop) A B x y,
  ext_rel A R ->
  rel_app (inject_rel R A B) x y ->
  x A /\ y B /\ R x y.
Proof.
unfold inject_rel, rel_app in |- *; intros.
specialize subset_elim1 with (1 := H0); intro.
elim subset_elim2 with (1 := H0); intros.
assert (x A).
 rewrite <- (fst_def x y).
 apply fst_typ with B; trivial.
split; trivial.
split.
 rewrite <- (snd_def x y).
 apply snd_typ with A; trivial.

elim (H x (fst x0) y (snd x0)); intros; auto.
 rewrite <- H2; symmetry in |- *; apply fst_def.
 rewrite <- H2; symmetry in |- *; apply snd_def.
Qed.

Functions


Definition is_function f :=
  is_relation f /\
   x y y', rel_app f x y -> rel_app f x y' -> y == y'.

Definition app f x :=
  union (subset (rel_image f) (fun y => rel_app f x y)).

Instance app_morph : morph2 app.
Proof.
do 3 red; intros.
unfold app.
apply union_morph.
apply subset_morph.
 apply rel_image_morph; trivial.

 split; intros.
  rewrite <- H.
  rewrite <- H0; trivial.

  rewrite H.
  rewrite H0; trivial.
Qed.

Lemma app_defined : f x y,
  is_function f -> rel_app f x y -> app f x == y.
Proof.
unfold app, is_function in |- *; intros.
destruct H.
transitivity (union (singl y)).
 apply union_morph.
   apply singl_ext; intros.
  apply subset_intro; trivial.
    apply rel_image_intro with (1 := H0).
  elim subset_elim2 with (1 := H2); intros.
  rewrite <- H3 in H4; eauto.
 apply union_singl_eq.
Qed.

Lemma app_elim : f x,
  is_function f -> x rel_domain f -> rel_app f x (app f x).
Proof.
intros.
elim rel_image_ex with (1 := H0); intros.
 rewrite (app_defined f x x0); trivial.
Qed.

Typing

Definition func A B :=
  subset (rel A B)
    (fun r =>
       ( x, x A -> exists2 y, y B & rel_app r x y) /\
       ( x y y', rel_app r x y -> rel_app r x y' -> y == y')).

Instance func_mono :
  Proper (eq_set ==> incl_set ==> incl_set) func.
unfold func; intros A A' eqA B B' inclB z infunc.
specialize subset_elim1 with (1:=infunc); intro.
apply subset_elim2 in infunc.
destruct infunc.
apply subset_intro.
 eapply rel_mono; eauto.
 rewrite eqA; reflexivity.

 destruct H1.
 split; intros.
  rewrite <- eqA in H3.
  elim H1 with (1:=H3); intros.
  apply inclB in H4.
  rewrite <- H0 in H5.
  exists x1; auto.

 rewrite H0 in H3,H4|-; eauto.
Qed.

Instance func_morph : morph2 func.
Proof.
do 3 red; intros.
unfold func.
apply subset_morph.
 apply rel_morph; trivial.

 split; intros.
  destruct H2.
  split; intros; eauto.
  rewrite <- H in H4.
  elim H2 with (1:=H4); intros.
  exists x3; trivial.
  rewrite <- H0; trivial.

  destruct H2.
  split; intros; eauto.
  rewrite H in H4.
  elim H2 with (1:=H4); intros.
  exists x3; trivial.
  rewrite H0; trivial.
Qed.

Lemma func_rel_incl : A B, func A B rel A B.
Proof.
unfold func; red; intros; eapply subset_elim1; eauto.
Qed.

Lemma func_is_function : f A B, f func A B -> is_function f.
Proof.
red in |- *; intros.
split.
 apply rel_is_relation with A B.
   apply func_rel_incl; trivial.
 intros.
   unfold func in H.
   elim subset_elim2 with (1 := H); intros.
   destruct H3.
   apply H4 with x; rewrite <- H2; auto.
Qed.

Lemma fun_domain_func : f A B, f func A B -> rel_domain f == A.
Proof.
intros; apply eq_intro; intros.
 apply rel_domain_incl with f B; trivial.
   unfold func in H.
   apply subset_elim1 with (1 := H).
 unfold rel_domain in |- *.
   unfold func in H.
   elim subset_elim2 with (1 := H); intros.
   destruct H2.
   apply subset_intro.
  specialize subset_elim1 with (1 := H); unfold rel in |- *; intro.
    apply union_intro with (singl z).
   apply singl_intro.
   elim H2 with (1 := H0); intros.
     red in H6.
     rewrite <- H1 in H6.
     apply union_intro with (2 := H6).
     unfold couple in |- *.
     auto.
  elim H2 with (1 := H0); intros.
    rewrite <- H1 in H5.
    exists x0; trivial.
Qed.

Lemma app_typ :
   f x A B, f func A B -> x A -> app f x B.
Proof.
unfold func in |- *; intros.
specialize subset_elim2 with (1 := H); destruct 1; auto.
apply app_typ2 with f x A.
 apply func_rel_incl; trivial.
 apply app_elim.
  apply func_is_function with A B; trivial.
   rewrite (fun_domain_func _ _ _ H).
    trivial.
Qed.

Lemma func_narrow : f A B B',
  f func A B ->
  ( x, x A -> app f x B') ->
  f func A B'.
unfold func; intros.
specialize subset_elim1 with (1:=H); intro.
elim subset_elim2 with (1:=H); intros.
destruct H3.
apply subset_intro.
 apply relation_is_rel; intros.
  apply rel_is_relation with A B; trivial.

  apply rel_domain_incl with B; trivial.

  red; intros.
  unfold rel_image in H5.
  elim subset_elim2 with (1:=H5); clear H5; intros.
  destruct H6.
  rewrite H5.
  rewrite H2 in H6.
  rewrite (H4 x1 x0 (app x x1)); trivial.
   rewrite <- H2; apply H0.
   apply app_typ1 with f x0 B; trivial.
   rewrite H2; trivial.

   rewrite (app_defined x x1 x0); trivial.
   apply func_is_function with A B; trivial; rewrite <- H2; trivial.

 split; intros.
  elim H3 with x0; trivial; intros.
  rewrite <- H2 in H7.
  exists x1; trivial.
  rewrite <- (app_defined f x0 x1); auto.
  apply func_is_function with A B; trivial.

  rewrite H2 in H5,H6|-; eauto.
Qed.

Definition lam_rel (F:set->set) A B := inject_rel (fun x y => F x == y) A B.

Lemma lam_rel_is_func : A B f,
  ext_fun A f ->
  ( x, x A -> f x B) ->
  lam_rel f A B func A B.
Proof.
unfold lam_rel in |- *; intros.
unfold func in |- *.
apply subset_intro.
 apply inject_rel_is_rel.

 split; intros.
  exists (f x); auto.
  apply inject_rel_intro; auto.
   red in |- *; intros.
      rewrite H4.
      rewrite (H _ _ H2 H3).
     split; auto.
   reflexivity.
  elim inject_rel_elim with (2 := H1).
   destruct 2.
     elim inject_rel_elim with (2 := H2).
    destruct 2.
       rewrite <- H5.
       rewrite <- H8.
      reflexivity.
   red in |- *; intros.
      rewrite H8.
      rewrite (H _ _ H6 H7).
     split; auto.
   red in |- *; intros.
      rewrite H5.
      rewrite (H _ _ H3 H4).
     split; auto.
Qed.

Lemma beta_rel_eq : f x A B,
  ext_fun A f ->
  x A -> ( x, x A -> f x B) -> app (lam_rel f A B) x == f x.
Proof.
intros.
apply app_defined.
 apply func_is_function with A B.
   apply lam_rel_is_func; auto.
 unfold lam_rel in |- *.
   apply inject_rel_intro; auto.
  red in |- *; intros.
     rewrite H4.
     rewrite (H _ _ H2 H3); split; auto.
  reflexivity.
Qed.

Definition lam A F := replf A (fun x => couple x (F x)).

Lemma fun_elt_is_ext : A f,
  ext_fun A f ->
  ext_fun A (fun x => couple x (f x)).
do 2 red; intros.
apply couple_morph; auto.
Qed.
Hint Resolve fun_elt_is_ext.

Lemma lam_is_function : A f, ext_fun A f -> is_function (lam A f).
red; intros.
split; intros.
 red; intros.
 apply replf_elim in H0; auto.
 destruct H0.
 rewrite H1.
 rewrite fst_def; rewrite snd_def; reflexivity.

 red in H0,H1|-.
 apply replf_elim in H0; auto.
 apply replf_elim in H1; auto.
 destruct H0; destruct H1.
 apply couple_injection in H2; destruct H2.
 apply couple_injection in H3; destruct H3.
 rewrite H2 in H3.
 rewrite H5; rewrite H4; auto.
Qed.

Lemma lam_is_func : A B f,
  ext_fun A f ->
  ( x, x A -> f x B) ->
  lam A f func A B.
Proof.
unfold lam in |- *; intros.
unfold func in |- *.
apply subset_intro.
 apply relation_is_rel.
  destruct (lam_is_function _ _ H); trivial.

  unfold rel_domain; red; intros.
  apply subset_elim2 in H1; destruct H1.
  destruct H2.
  red in H2.
  apply replf_elim in H2; auto.
  destruct H2.
  apply couple_injection in H3; destruct H3.
  rewrite H1; rewrite H3; trivial.

  unfold rel_image; red; intros.
  apply subset_elim2 in H1; destruct H1.
  destruct H2.
  red in H2.
  apply replf_elim in H2; auto.
  destruct H2.
  apply couple_injection in H3; destruct H3.
  rewrite H1; rewrite H4; auto.

 split; intros.
  exists (f x); auto.
  red.
  apply replf_intro with x; auto.
  reflexivity.

  destruct lam_is_function with (1:=H).
  eauto.
Qed.

Lemma beta_eq : f x A,
  ext_fun A f -> x A -> app (lam A f) x == f x.
Proof.
unfold lam.
intros.
apply app_defined.
 split; intros.
  red; intros.
  apply replf_elim in H1; auto.
  destruct H1.
  rewrite H2.
  rewrite fst_def; rewrite snd_def; reflexivity.

  destruct lam_is_function with (1:=H); eauto.

 red.
 apply replf_intro with x; auto.
 reflexivity.
Qed.

Dependent typing

Definition dep_image (A:set) (B:set->set) := replf A B.

Lemma dep_image_ext :
   x1 x2 f1 f2,
  x1 == x2 ->
  eq_fun x1 f1 f2 ->
  dep_image x1 f1 == dep_image x2 f2.
Proof.
intros.
unfold dep_image.
apply replf_morph; trivial.
Qed.

Definition dep_func (A:set) (B:set->set) :=
  subset (func A (union (dep_image A B)))
    (fun f => x, x A -> app f x B x).

Lemma dep_func_ext :
   x1 x2 f1 f2,
  x1 == x2 ->
  eq_fun x1 f1 f2 ->
  dep_func x1 f1 == dep_func x2 f2.
Proof.
intros.
unfold dep_func.
apply subset_morph; trivial.
 apply func_morph; trivial.
 apply union_morph.
 apply dep_image_ext; trivial.

 split; intros.
  rewrite <- H in H3.
  rewrite <- (H0 x0 x0); auto; reflexivity.

  rewrite (H0 x0 x0); trivial; try reflexivity.
  rewrite H in H3; auto.
Qed.

Lemma dep_func_mono : A A' F F',
  ext_fun A F ->
  ext_fun A' F' ->
  A == A' ->
  ( x, x A -> F x F' x) ->
  dep_func A F dep_func A' F'.
unfold dep_func; red; intros A A' F F' eF eF' eqA H z H0.
rewrite subset_ax in H0|-*.
destruct H0; split.
 clear H1; revert z H0; apply func_mono; auto with *.
 red; intros.
 unfold dep_image in H0|-*.
 rewrite union_ax in H0|-*.
 destruct H0.
 rewrite replf_ax in H1; trivial.
 destruct H1.
 exists (F' x0).
  rewrite H2 in H0.
  apply H; auto.

  rewrite eqA in H1.
  rewrite replf_ax; auto.
  exists x0; auto with *.

 destruct H1.
 exists x; trivial.
 intros.
 rewrite <- eqA in H3.
 apply H; auto.
Qed.

Lemma dep_func_intro : f dom F,
  ext_fun dom f ->
  ext_fun dom F ->
  ( x, x dom -> f x F x) ->
  lam dom f dep_func dom F.
Proof.
intros.
assert ( x, x dom -> f x union (dep_image dom F)).
 intros.
 apply union_intro with (F x); auto.
 unfold dep_image.
 apply replf_intro with x; trivial.
 reflexivity.
unfold dep_func.
apply subset_intro.
 apply lam_is_func; trivial.

 intros.
 rewrite beta_eq; auto.
Qed.

Lemma func_eta : f A B,
  f func A B ->
  f == lam A (fun x => app f x).
intros.
specialize subset_elim2 with (1:=H); intro.
destruct H0.
destruct H1.
clear H2.
apply eq_intro; intros.
 specialize subset_elim1 with (1:=H); intros is_rel.
 apply power_elim with (2:= H2) in is_rel.
 specialize fst_typ with (1:=is_rel); intros.
 destruct H1 with (1:= H3); clear H1.
 apply surj_pair in is_rel.
 apply func_is_function in H.
 red in H5; rewrite <- H0 in H5; clear x H0.
 specialize app_defined with (1:=H) (2:=H5); intros.
 destruct H.
 rewrite is_rel in H2.
 specialize H1 with (1:=H2) (2:=H5).
 rewrite <- H1 in H0.
 unfold lam.
 apply replf_intro with (fst z); auto.
  do 2 red; intros.
  rewrite H7; reflexivity.
 rewrite H0; trivial.

 apply replf_elim in H2.
  destruct H2.
  rewrite H3.
  apply app_elim.
   apply func_is_function in H; trivial.
  apply H1 in H2.
  destruct H2.
  red in H4; rewrite <- H0 in H4.
  apply rel_domain_intro with x1; trivial.

  do 2 red; intros.
  rewrite H4; reflexivity.
Qed.

Lemma dep_func_eta : f dom F,
  f dep_func dom F ->
  f == lam dom (fun x => app f x).
intros.
apply subset_elim1 in H.
apply func_eta with (1:=H).
Qed.

Lemma dep_func_incl_func : A B,
  dep_func A B func A (union (dep_image A B)).
Proof.
unfold dep_func in |- *; red in |- *; intros.
apply subset_elim1 with (1 := H).
Qed.

Lemma dep_func_elim :
   f x A B, f dep_func A B -> x A -> app f x B x.
Proof.
unfold dep_func in |- *; intros.
elim subset_elim2 with (1 := H); intros.
rewrite H1.
auto.
Qed.

Aczel's encoding of functions

Characterizing functions

Definition is_cc_fun A f :=
   c, c f -> c == couple (fst c) (snd c) /\ fst c A.

Instance is_cc_fun_morph : Proper (eq_set ==> eq_set ==> iff) is_cc_fun.
apply morph_impl_iff2; auto with *.
do 5 red; intros.
rewrite <- H; rewrite <- H0 in H2; auto.
Qed.

Function constructor

Definition cc_lam (x:set) (y:set->set) : set :=
  sup x (fun x' => replf (y x') (fun y' => couple x' y')).

Instance cc_lam_morph : Proper (eq_set ==> (eq_set ==> eq_set) ==> eq_set) cc_lam.
unfold cc_lam; do 3 red; intros.
apply sup_morph; trivial.
red; intros.
apply replf_morph.
 apply H0; trivial.

 red; intros; apply couple_morph; trivial.
Qed.

Lemma cc_lam_def dom f z :
  ext_fun dom f ->
  (z cc_lam dom f <->
   exists2 x, x dom & exists2 y, y f x & z == couple x y).
unfold cc_lam; intros.
rewrite sup_ax.
 apply ex2_morph; red; intros; auto with *.
 rewrite replf_ax; auto with *.
 do 2 red; intros; apply couple_morph; auto with *.

 do 2 red; intros; apply replf_morph; auto.
 red; intros; apply couple_morph; auto with *.
Qed.

Lemma is_cc_fun_lam A F :
  ext_fun A F ->
  is_cc_fun A (cc_lam A F).
red; intros.
rewrite cc_lam_def in H0; trivial; destruct H0 as (x,?,(y,_,?)).
rewrite H1; rewrite fst_def; rewrite snd_def; auto with *.
Qed.

Lemma cc_lam_ext :
   x1 x2 f1 f2,
  x1 == x2 ->
  eq_fun x1 f1 f2 ->
  cc_lam x1 f1 == cc_lam x2 f2.
intros.
assert (ext_fun x1 f1).
 apply eq_fun_ext in H0; trivial.
assert (ext_fun x2 f2).
 do 2 red; intros.
 rewrite <-H in H2.
 rewrite <- (H0 x x'); trivial.
 symmetry; apply H0; trivial; try reflexivity.
rewrite eq_set_ax; intros z.
do 2 (rewrite cc_lam_def; trivial).
split; (destruct 1 as (x,?,h); destruct h as (y,?,?); exists x;[|exists y]); trivial.
 rewrite <- H; trivial.
 revert H4; apply eq_elim; apply H0; auto with *.
 rewrite H; auto.
 revert H4; apply eq_elim; symmetry; apply H0; auto with *.
 rewrite H; trivial.
Qed.

Lemma cc_impredicative_lam : dom F,
  ext_fun dom F ->
  ( x, x dom -> F x == empty) ->
  cc_lam dom F == empty.
Proof.
intros.
apply empty_ext; red in |- *; intros.
rewrite cc_lam_def in H1; trivial; destruct H1 as (z,?,(y,?,?)).
rewrite H0 in H2; trivial.
apply empty_ax with y; trivial.
Qed.

Application

Definition cc_app (x y:set) : set :=
  rel_image (subset x (fun p => fst p == y)).

Instance cc_app_morph : morph2 cc_app.
do 3 red; unfold cc_app in |- *; intros.
apply rel_image_morph.
apply subset_morph; trivial.
red; intros.
rewrite H0.
reflexivity.
Qed.

Lemma couple_in_app : x z f,
  couple x z f <-> z cc_app f x.
unfold cc_app, rel_image; split; intros.
 apply subset_intro.
  apply union_intro with (pair x z).
   apply pair_intro2.

   apply union_intro with (couple x z).
    apply pair_intro2.

    apply subset_intro; trivial.
    apply fst_def.

  exists x.
  red; apply subset_intro; trivial.
  apply fst_def.

 rewrite subset_ax in H; destruct H.
 destruct H0.
 destruct H1.
 red in H1.
 rewrite subset_ax in H1; destruct H1.
 destruct H2.
 rewrite <- H0 in H1.
 rewrite <- H2 in H3; rewrite fst_def in H3.
 rewrite H3 in H1; trivial.
Qed.

Lemma cc_app_empty : x, cc_app empty x == empty.
intro.
apply empty_ext; red; intros.
rewrite <- couple_in_app in H.
apply empty_ax in H; trivial.
Qed.

Beta reduction

Lemma cc_beta_eq : dom F x,
  ext_fun dom F ->
  x dom ->
  cc_app (cc_lam dom F) x == F x.
Proof.
intros.
apply eq_intro; intros.
 rewrite <- couple_in_app in H1.
 rewrite cc_lam_def in H1; trivial.
 destruct H1 as (x',?,(y,?,?)).
 apply couple_injection in H3; destruct H3.
 rewrite H4; revert H2; apply eq_elim; apply H; auto with *.

 rewrite <- couple_in_app.
 rewrite cc_lam_def; eauto with *.
Qed.

Eta reduction

Lemma cc_eta_eq' : dom f,
  is_cc_fun dom f ->
  f == cc_lam dom (fun x => cc_app f x).
unfold is_cc_fun.
intros.
assert (am : ext_fun dom (fun x => cc_app f x)).
 do 2 red; intros; apply cc_app_morph; auto with *.
apply eq_intro; intros.
 specialize H with (1:=H0); destruct H.
 rewrite cc_lam_def; trivial.
 exists (fst z); trivial.
 exists (snd z); trivial.
 rewrite <- couple_in_app; rewrite <- H; trivial.

 rewrite cc_lam_def in H0; trivial.
 destruct H0 as (x,?,(y,?,?)).
 rewrite H2; apply couple_in_app; trivial.
Qed.

Typing: dependent products

Definition cc_prod (x:set) (y:set->set) : set :=
  replf (dep_func x y)
    (fun f => cc_lam x (fun x' => app f x')).

Lemma cc_prod_ext :
   x1 x2 f1 f2,
  x1 == x2 ->
  eq_fun x1 f1 f2 ->
  cc_prod x1 f1 == cc_prod x2 f2.
Proof.
unfold cc_prod in |- *; intros.
apply replf_morph; intros; trivial.
 apply dep_func_ext; trivial.

 red; intros.
 apply cc_lam_ext; auto.
 red; intros.
 apply app_morph; trivial.
Qed.

Instance cc_prod_morph : Proper (eq_set ==> (eq_set ==> eq_set) ==> eq_set) cc_prod.
do 3 red; intros; apply cc_prod_ext; trivial.
red; intros; apply H0; trivial.
Qed.

Lemma cc_prod_fun1 : A x,
  ext_fun A (fun f => cc_lam x (fun x' => app f x')).
Proof.
do 2 red; intros.
apply cc_lam_ext; try reflexivity; red; intros.
apply app_morph; trivial.
Qed.
Hint Resolve cc_prod_fun1.

Lemma cc_prod_is_cc_fun : A B f,
  f cc_prod A B -> is_cc_fun A f.
intros.
unfold cc_prod in H.
rewrite replf_ax in H; auto.
destruct H.
rewrite H0.
apply is_cc_fun_lam; auto.
do 2 red; intros; apply app_morph; auto with *.
Qed.
Hint Resolve cc_prod_is_cc_fun.

Definition cc_arr A B := cc_prod A (fun _ => B).

Instance cc_arr_morph : morph2 cc_arr.
do 3 red; intros.
apply cc_prod_morph; trivial.
red; trivial.
Qed.

Lemma cc_prod_intro : dom f F,
  ext_fun dom f ->
  ext_fun dom F ->
  ( x, x dom -> f x F x) ->
  cc_lam dom f cc_prod dom F.
unfold cc_prod in |- *.
intros.
assert ( x, x dom -> f x union (dep_image dom F)).
 intros.
 apply union_intro with (F x); auto.
 unfold dep_image.
 apply replf_intro with x; auto.
 reflexivity.
apply replf_intro with (lam dom f); trivial.
 apply dep_func_intro; trivial.

 apply cc_lam_ext; intros.
  reflexivity.

  red; intros.
  rewrite beta_eq; auto.
  rewrite <- H4; trivial.
Qed.

Lemma cc_prod_elim : dom f x F,
  f cc_prod dom F ->
  x dom ->
  cc_app f x F x.
intros.
unfold cc_prod in H.
elim replf_elim with (2 := H); clear H; intros; auto.
rewrite H1; clear H1.
rewrite cc_beta_eq; auto.
 apply dep_func_elim with dom; trivial.

 do 2 red; intros.
 rewrite H2; reflexivity.
Qed.

Lemma cc_app_typ f v A B B' :
  f cc_prod A B ->
  B' == B v ->
  v A ->
  cc_app f v B'.
intros.
rewrite H0; apply cc_prod_elim with (1:=H); trivial.
Qed.

Lemma cc_arr_intro : A B F,
  ext_fun A F ->
  ( x, x A -> F x B) ->
  cc_lam A F cc_arr A B.
unfold cc_arr; intros.
apply cc_prod_intro; auto.
do 2 red; reflexivity.
Qed.

Lemma cc_arr_elim : f x A B,
  f cc_arr A B ->
  x A ->
  cc_app f x B.
intros.
apply cc_prod_elim with (1:=H); trivial.
Qed.

Lemma cc_eta_eq: dom F f,
  f cc_prod dom F ->
  f == cc_lam dom (fun x => cc_app f x).
intros.
apply cc_eta_eq'; eauto.
Qed.

Lemma cc_prod_covariant : dom dom' F G,
  ext_fun dom' G ->
  dom == dom' ->
  ( x, x dom -> F x G x) ->
  cc_prod dom F cc_prod dom' G.
red; intros.
setoid_replace (cc_prod dom' G) with (cc_prod dom G).
 specialize cc_eta_eq with (1:=H2); intro.
 rewrite H3.
 apply cc_prod_intro; trivial.
  red; red; intros.
  rewrite H5; auto with *.

  red; red; intros.
  rewrite H0 in H4; apply H; trivial.

  intros.
  apply H1; trivial.
  apply cc_prod_elim with (1:=H2); trivial.

 apply cc_prod_ext; trivial.
 symmetry; trivial.
Qed.

Lemma cc_prod_intro' : (dom dom': set) (f F : set -> set),
       ext_fun dom f ->
       ext_fun dom' F ->
       dom == dom' ->
       ( x : set, x dom -> f x F x) ->
       cc_lam dom f cc_prod dom' F.
intros.
cut (cc_lam dom f cc_prod dom F).
 apply cc_prod_covariant; auto with *.
apply cc_prod_intro; intros; auto.
do 2 red; intros.
apply H0; trivial.
rewrite <- H1; trivial.
Qed.