ImpAlg.Combinators
Set Implicit Arguments.
Set Contextual Implicit.
Require Import Utf8.
Require Import Setoid.
Require Import Morphisms.
Require Import Relation_Definitions.
Require Import TLC.LibLN.
Require Import Arith.
Require Import ImpAlg.Lattices.
Require Import ImpAlg.ImplicativeStructures.
Require Import Sets.Ensembles.
Require Import ImpAlg.Lambda.
Require Import ImpAlg.Adequacy.
Set Contextual Implicit.
Require Import Utf8.
Require Import Setoid.
Require Import Morphisms.
Require Import Relation_Definitions.
Require Import TLC.LibLN.
Require Import Arith.
Require Import ImpAlg.Lattices.
Require Import ImpAlg.ImplicativeStructures.
Require Import Sets.Ensembles.
Require Import ImpAlg.Lambda.
Require Import ImpAlg.Adequacy.
We start by defining some tactics that are useful in the sequel.
Ltac adjunction_mon:=
repeat
match goal with
| |- (_ ↦ ?a ≤ _ ↦ ?a) => apply arrow_mon_l
| |- (?a ↦ _ ≤ ?a ↦ _ )=> apply arrow_mon_r
| |- _@?a ≤ _@?a => apply app_mon_l
| |- _ ≤ ?a ↦ (_@?a)=> apply adjunction
| |- ?a ≤ _ ↦ (?a@_)=> apply adjunction
| |- (?a ↦ _)@?a ≤ _ => apply adjunction
| |- (_ ↦ ?a)@_ ≤ ?a => apply adjunction
end;try (apply ord_refl); auto.
Ltac repeat_meet_intro :=
repeat
(apply meet_intro;intros ?x ?Hx;
repeat (
match goal with
| Ha: exists x, _ |- _ => destruct Ha as (?x,?Hx)
| Ha: ?a = _ |- _ ≤ ?a => rewrite Ha
| Ha: _ ∧ _ |- _ => destruct Ha as (?Ha1,?Ha2)
end)
).
Ltac auto_meet_elim :=
apply meet_elim;
match goal with
| |- (exists !a, ?b ↦ _ = ?a ↦ _ )=> exists ?b;reflexivity
| |- _ => auto
end.
Definition Succ := Datatypes.S.
Ltac find_translated :=
repeat (
match goal with
| |- translated (trm_abs _ ) _ =>
apply tr_abs;intros;unfold open_trm;simpl;unfold open_rec_trm;simpl;unfold Succ;repeat case_nat
| |- translated (trm_app _ _) _ => apply tr_app
| |- translated (trm_cvar _) _ => apply tr_cvar
end
).
Ltac find_translated_typ :=
repeat (
match goal with
| |- translated_typ (typ_fall _ ) _ =>
apply tr_typ_fall;intros;unfold open_typ;unfold open_rec_typ
| |- translated_typ (typ_arrow _ _) _ => apply tr_typ_arrow
| |- translated_typ (typ_cvar _) _ => apply tr_typ_var
| |- translated_typ (If ?a = ?a then _ else _ ) _ => rewrite~ If_l
| |- translated_typ (_ _ (If Succ ?a = 0 then _ else _ ) _ ) _ => rewrite~ If_r
end).
repeat
match goal with
| |- (_ ↦ ?a ≤ _ ↦ ?a) => apply arrow_mon_l
| |- (?a ↦ _ ≤ ?a ↦ _ )=> apply arrow_mon_r
| |- _@?a ≤ _@?a => apply app_mon_l
| |- _ ≤ ?a ↦ (_@?a)=> apply adjunction
| |- ?a ≤ _ ↦ (?a@_)=> apply adjunction
| |- (?a ↦ _)@?a ≤ _ => apply adjunction
| |- (_ ↦ ?a)@_ ≤ ?a => apply adjunction
end;try (apply ord_refl); auto.
Ltac repeat_meet_intro :=
repeat
(apply meet_intro;intros ?x ?Hx;
repeat (
match goal with
| Ha: exists x, _ |- _ => destruct Ha as (?x,?Hx)
| Ha: ?a = _ |- _ ≤ ?a => rewrite Ha
| Ha: _ ∧ _ |- _ => destruct Ha as (?Ha1,?Ha2)
end)
).
Ltac auto_meet_elim :=
apply meet_elim;
match goal with
| |- (exists !a, ?b ↦ _ = ?a ↦ _ )=> exists ?b;reflexivity
| |- _ => auto
end.
Definition Succ := Datatypes.S.
Ltac find_translated :=
repeat (
match goal with
| |- translated (trm_abs _ ) _ =>
apply tr_abs;intros;unfold open_trm;simpl;unfold open_rec_trm;simpl;unfold Succ;repeat case_nat
| |- translated (trm_app _ _) _ => apply tr_app
| |- translated (trm_cvar _) _ => apply tr_cvar
end
).
Ltac find_translated_typ :=
repeat (
match goal with
| |- translated_typ (typ_fall _ ) _ =>
apply tr_typ_fall;intros;unfold open_typ;unfold open_rec_typ
| |- translated_typ (typ_arrow _ _) _ => apply tr_typ_arrow
| |- translated_typ (typ_cvar _) _ => apply tr_typ_var
| |- translated_typ (If ?a = ?a then _ else _ ) _ => rewrite~ If_l
| |- translated_typ (_ _ (If Succ ?a = 0 then _ else _ ) _ ) _ => rewrite~ If_r
end).
Combinators
Section Combinators.
Context `{IS:ImplicativeStructure}.
Definition env:=@env X.
Definition codom:=@codom X.
Definition fv_trm:=@fv_trm X.
Definition fv_typ:=@fv_typ X.
We define again the tactis to pick fresh variables.
Ltac gather_vars :=
let A := gather_vars_with (fun x : vars => x) in
let B := gather_vars_with (fun x : var => \{x}) in
let C := gather_vars_with (fun x : env => (dom x)\u (codom x)) in
let D := gather_vars_with (fun x : trm => fv_trm x) in
let E := gather_vars_with (fun x : typ => fv_typ x) in
constr:(A \u B \u C \u D \u E).
Ltac pick_fresh Y :=
let L := gather_vars in (pick_fresh_gen L Y).
Tactic Notation "apply_fresh" constr(T) "as" ident(x) :=
apply_fresh_base T gather_vars x.
Tactic Notation "apply_fresh" "*" constr(T) "as" ident(x) :=
apply_fresh T as x; auto_star.
Tactic Notation "apply_fresh" constr(T) :=
apply_fresh_base T gather_vars ltac_no_arg.
Tactic Notation "apply_fresh" "*" constr(T) :=
apply_fresh T; auto_star.
let A := gather_vars_with (fun x : vars => x) in
let B := gather_vars_with (fun x : var => \{x}) in
let C := gather_vars_with (fun x : env => (dom x)\u (codom x)) in
let D := gather_vars_with (fun x : trm => fv_trm x) in
let E := gather_vars_with (fun x : typ => fv_typ x) in
constr:(A \u B \u C \u D \u E).
Ltac pick_fresh Y :=
let L := gather_vars in (pick_fresh_gen L Y).
Tactic Notation "apply_fresh" constr(T) "as" ident(x) :=
apply_fresh_base T gather_vars x.
Tactic Notation "apply_fresh" "*" constr(T) "as" ident(x) :=
apply_fresh T as x; auto_star.
Tactic Notation "apply_fresh" constr(T) :=
apply_fresh_base T gather_vars ltac_no_arg.
Tactic Notation "apply_fresh" "*" constr(T) :=
apply_fresh T; auto_star.
We define a simple tactic to automatize the proof that a pre-term is a term,
when it is the case.
Ltac fresh_term_abs :=
let L0:=gather_vars in let L1 := beautify_fset L0 in
apply (@term_abs _ L1);intros.
Ltac fresh_typing_abs :=
let L0:=gather_vars in let L1 := beautify_fset L0 in
apply (@typing_abs _ L1);intros.
Ltac autoterm :=
repeat (
try (apply term_cc);
try (apply term_var);
try (fresh_term_abs);
try (apply term_app);
try (unfold Succ);
try (case_nat)
).
A convenient notation for λ-terms.
Notation "λ+ t":= (trm_abs (t:trm)) (at level 69, right associativity).
Notation "[ t ] u":= (trm_app (t:trm) u ) (at level 69, right associativity).
Notation "$ n":= (@trm_bvar X n) (at level 69, right associativity).
We prove that I^A is equal to its principal type.
Note that we use the tactic "find_translated" to automatize the proof
that I^A = λ(fun x=>x).
Proposition 18.1
Proposition 18.2
Lemma lambda_K:
K = λ- (fun x=> λ- (fun y => x)).
Proof.
unfold abs.
apply meet_same_set.
split;intros x [a Ha];
exists a;
rewrite Ha,arrow_meet in *;
apply meet_same_set;
[ | apply same_set_sym];
apply arrow_prenex with (f:=fun x => (fun y => y ↦ x)).
Qed.
Lemma translated_K : translated lambdaK K.
Proof.
rewrite lambda_K.
unfold lambdaK.
find_translated.
Qed.
K = λ- (fun x=> λ- (fun y => x)).
Proof.
unfold abs.
apply meet_same_set.
split;intros x [a Ha];
exists a;
rewrite Ha,arrow_meet in *;
apply meet_same_set;
[ | apply same_set_sym];
apply arrow_prenex with (f:=fun x => (fun y => y ↦ x)).
Qed.
Lemma translated_K : translated lambdaK K.
Proof.
rewrite lambda_K.
unfold lambdaK.
find_translated.
Qed.
Definition S:= ⋂[a] (⋂[b] ⋂[c] ((a ↦ b ↦ c) ↦ (a ↦ b) ↦ a ↦ c)).
Definition lambdaS:=λ+ λ+ λ+ [[$2] $0] ([$1] $0).
Proposition 18.3
Lemma lambda_S: S = λ- (fun x => λ- (fun y => λ- (fun z => (x@z)@(y@z)))).
Proof.
unfold S.
apply (ord_antisym).
- apply meet_intro;intros x [a Ha].
unfold abs in Ha at 1. rewrite arrow_meet in Ha. rewrite Ha.
apply meet_intro;intros y [z [[b Hb] Hy]]. subst. unfold abs.
do 2 (rewrite arrow_meet).
apply meet_intro;intros w [v [[u [[c Hc] Hv]] Hw]]. subst.
apply (ord_trans _ (⊓ (λ z : X, ∃ d : X, z = (c ↦ (b@c) ↦ d) ↦ (c ↦ (b@c)) ↦ c ↦ d))).
+ apply (double_meet_elim (fun c => fun b => ⊓ (λ z : X, ∃ d : X, z = (c ↦ b ↦ d) ↦ (c ↦ (b)) ↦ c ↦ d))).
+ unfold app at 3. repeat (rewrite arrow_meet).
apply meet_intro;intros z [y [[w [[d [Hd Hw]] Hy]] Hz]]. subst.
apply meet_elim_trans. later;split;[exists d;reflexivity|].
apply arrow_mon;adjunction_mon. apply adjunction. apply Hd.
- repeat_meet_intro. unfold abs.
apply (ord_trans _ ((a ↦ b ↦ c) ↦ ⊓(λ x1 : X,∃ a1 : X,
x1 = a1 ↦ ⊓ (λ x2 : X, ∃ a2 : X, x2 = a2 ↦ (a ↦ b ↦ c) @ a2 @ (a1 @ a2))))).
+ apply meet_elim. exists (a ↦ b ↦ c). reflexivity.
+ apply arrow_mon_r.
apply (ord_trans _ ((a ↦ b) ↦ ⊓ (λ x2 : X, ∃ a2 : X, x2 = a2 ↦ (a ↦ b ↦ c) @ a2 @ ((a ↦ b) @ a2)))).
* apply meet_elim. exists (a ↦ b). reflexivity.
* apply arrow_mon_r.
apply (ord_trans _ (a ↦ (a ↦ b ↦ c) @ a @ ((a ↦ b) @ a))).
apply meet_elim;exists a;reflexivity.
repeat (try (apply arrow_mon_r);try (apply arrow_mon_l);apply adjunction).
apply ord_refl.
Qed.
Lemma translated_S: translated lambdaS S.
Proof.
rewrite lambda_S. unfold lambdaS. find_translated.
Qed.
Proof.
unfold S.
apply (ord_antisym).
- apply meet_intro;intros x [a Ha].
unfold abs in Ha at 1. rewrite arrow_meet in Ha. rewrite Ha.
apply meet_intro;intros y [z [[b Hb] Hy]]. subst. unfold abs.
do 2 (rewrite arrow_meet).
apply meet_intro;intros w [v [[u [[c Hc] Hv]] Hw]]. subst.
apply (ord_trans _ (⊓ (λ z : X, ∃ d : X, z = (c ↦ (b@c) ↦ d) ↦ (c ↦ (b@c)) ↦ c ↦ d))).
+ apply (double_meet_elim (fun c => fun b => ⊓ (λ z : X, ∃ d : X, z = (c ↦ b ↦ d) ↦ (c ↦ (b)) ↦ c ↦ d))).
+ unfold app at 3. repeat (rewrite arrow_meet).
apply meet_intro;intros z [y [[w [[d [Hd Hw]] Hy]] Hz]]. subst.
apply meet_elim_trans. later;split;[exists d;reflexivity|].
apply arrow_mon;adjunction_mon. apply adjunction. apply Hd.
- repeat_meet_intro. unfold abs.
apply (ord_trans _ ((a ↦ b ↦ c) ↦ ⊓(λ x1 : X,∃ a1 : X,
x1 = a1 ↦ ⊓ (λ x2 : X, ∃ a2 : X, x2 = a2 ↦ (a ↦ b ↦ c) @ a2 @ (a1 @ a2))))).
+ apply meet_elim. exists (a ↦ b ↦ c). reflexivity.
+ apply arrow_mon_r.
apply (ord_trans _ ((a ↦ b) ↦ ⊓ (λ x2 : X, ∃ a2 : X, x2 = a2 ↦ (a ↦ b ↦ c) @ a2 @ ((a ↦ b) @ a2)))).
* apply meet_elim. exists (a ↦ b). reflexivity.
* apply arrow_mon_r.
apply (ord_trans _ (a ↦ (a ↦ b ↦ c) @ a @ ((a ↦ b) @ a))).
apply meet_elim;exists a;reflexivity.
repeat (try (apply arrow_mon_r);try (apply arrow_mon_l);apply adjunction).
apply ord_refl.
Qed.
Lemma translated_S: translated lambdaS S.
Proof.
rewrite lambda_S. unfold lambdaS. find_translated.
Qed.
Lemma Id_SK : (S @ K) @ K ≤ Id.
Proof.
rewrite lambda_S.
apply (ord_trans _ ((λ- (λ y : X, λ- (λ z : X, K @ z @ (y @ z)))) @ K )).
- apply app_mon_l.
apply (betarule (fun x => (λ- (λ y : X, λ- (λ z : X, x @ z @ (y @ z))))) K).
- apply (ord_trans _ (λ- (λ z : X, K @ z @ (K @ z)))).
apply (betarule (fun y => λ- (λ z : X, K @ z @ (y @ z))) K).
rewrite lambda_Id.
repeat_meet_intro.
apply adjunction.
apply (ord_trans _ (K @ a @ (K @ a))).
apply (betarule (fun z => K @ z @ (K @ z)) a).
unfold K at 1.
do 2 (apply adjunction).
apply (double_meet_elim (fun x => fun y => x ↦ y ↦ x)).
Qed.
Proposition 18.4
Lemma lambda_W:
W = λ- (fun x => λ- (fun y => (x @ y) @ y)).
Proof.
unfold abs,W.
apply ord_antisym.
- repeat_meet_intro. rewrite arrow_meet. apply meet_intro.
intros y [z [[c Hz] Hy]]. rewrite Hy,Hz.
clear y z Hy Hz x Hx. unfold app.
do 2 (rewrite arrow_meet).
apply meet_intro; intros w [y [[z [Hz Hy]] Hw]].
rewrite Hw,Hy. rewrite (double_meet).
apply (ord_trans _ ((c ↦ c ↦ z) ↦ c ↦ z)).
+ apply (double_meet_elim (fun x => fun y => (x ↦ x ↦ y) ↦ x ↦ y)).
+ apply arrow_mon_l. apply adjunction. apply Hz.
- repeat_meet_intro.
apply (ord_trans _ ((a ↦ a ↦ b) ↦ ⊓ (λ x0 : X, ∃ a0 : X, x0 = a0 ↦ (a ↦ a ↦ b)@ a0 @ a0))).
+ apply meet_elim. exists (a ↦ a ↦ b). reflexivity.
+ apply arrow_mon_r. apply (ord_trans _ (a ↦ (a ↦ a ↦ b) @ a @ a)).
* apply meet_elim. exists a;reflexivity.
* adjunction_mon. apply adjunction. adjunction_mon.
Qed.
Lemma translated_W: translated lambdaW W.
Proof.
unfold lambdaW.
rewrite lambda_W.
find_translated.
Qed.
(* C ≡ λxyz . xzy*)
λxy.xy
We prove one more equality, namely that:Definition Easy:= ⊓ (λ x:X, ∃ a, x= ⊓ (λ y:X, ∃ b, y = ( (a ↦ b) ↦ a ↦ b))).
Lemma lambda_Easy:
Easy = λ- (fun x => λ- (fun y => x @ y)).
Proof.
unfold abs,Easy.
apply ord_antisym.
- apply meet_intro;intros x (a,Ha). subst. rewrite arrow_meet.
apply meet_intro;intros b [x [[c Hx] H]]. subst. unfold app.
do 2 (rewrite arrow_meet).
apply meet_intro; intros w [y [[z [Hz Hy]] Hw]]. subst.
rewrite (double_meet ). apply (ord_trans _ ((c ↦ z) ↦ c ↦ z)).
+ apply (double_meet_elim (fun x => fun y => (x ↦ y) ↦ x ↦ y)).
+ apply arrow_mon_l. apply Hz.
- apply meet_intro;intros. destruct H as [a Ha]. subst.
apply meet_intro;intros b [c Hb]. subst.
apply (ord_trans _ ((a ↦ c) ↦ ⊓ (λ x0 : X, ∃ a0 : X, x0 = a0 ↦ (a ↦ c) @ a0))).
+ apply meet_elim. exists (a ↦ c). reflexivity.
+ apply arrow_mon_r. apply (ord_trans _ (a ↦ (a ↦ c) @ a)).
* apply meet_elim. exists a;reflexivity.
* apply arrow_mon_r. apply meet_elim. apply ord_refl.
Qed.
Definition lambdaEasy:= λ+ λ+ [$1] $0.
Lemma translated_Easy: translated lambdaEasy Easy.
Proof.
unfold lambdaEasy.
rewrite lambda_Easy.
find_translated.
Qed.
Definition lambdaB:= λ+ λ+ λ+ [$2] ([$1] $0).
Definition B := ⋂[ a] (⋂[ b] (⋂[ c] ((a ↦ b) ↦ (c ↦ a) ↦ c ↦ b))).
Lemma lambda_B:
B = λ- (fun x => λ- (fun y => λ- (fun z => x@ (y @ z)))).
Proof.
unfold abs,B.
apply ord_antisym.
- repeat_meet_intro. rewrite arrow_meet.
apply meet_intro. intros y [z [[d Hz] Hy]]. subst.
do 2 (rewrite arrow_meet).
apply meet_intro; intros x [b [[z [[c Hz] Hy]] Hw]]. subst.
unfold app. do 3 (rewrite arrow_meet).
apply meet_intro. intros z [x [[x' [[b [Hz Hy]] H']] H]]. subst.
eapply ord_trans;[|apply arrow_mon_l;exact Hz].
apply meet_elim_trans.
later;split;[exists (⊓ (λ x : X, d ≤ c ↦ x));reflexivity|].
clear Hz a.
eapply meet_elim_trans. later;split;[exists b;reflexivity|].
eapply meet_elim_trans. later;split;[exists c;reflexivity|].
adjunction_mon.
apply adjunction.
reflexivity.
- repeat_meet_intro.
auto_meet_elim_trans. apply arrow_mon_r.
auto_meet_elim_trans. apply arrow_mon_r.
auto_meet_elim_trans. apply arrow_mon_r.
adjunction_mon.
Qed.
Hint Resolve lambda_S lambda_K lambda_Id translated_Id translated_S translated_K tr_cc.
Combinatory terms
Inductive comb :=
| combS : comb
| combK : comb
| combCC : comb
| combApp: comb → comb → comb
.
Fixpoint trm_comb c:=
match c with
| combS => lambdaS
| combK => lambdaK
| combCC => trm_cc
| combApp c d => trm_app (trm_comb c) (trm_comb d)
end.
Fixpoint imp_comb c:=
match c with
| combS => S
| combK => K
| combCC => cc
| combApp c d => (imp_comb c)@(imp_comb d)
end.
Inductive combinator : X → Prop :=
| comb_S : combinator S
| comb_K : combinator K
| comb_Id : combinator Id
| comb_cc : combinator cc
| comb_app: ∀ A B, combinator A → combinator B → combinator (A@B).
Hint Resolve comb_S comb_K comb_Id comb_cc comb_app.
Lemma translated_comb: ∀ c, translated (trm_comb c) (imp_comb c).
Proof.
intro c; induction c;simpl;auto.
apply* tr_app.
Qed.
Lemma combinator_comb: ∀ c, combinator (imp_comb c).
Proof.
intro c; induction c;simpl;auto.
Qed.
For the combinatory completeness, we need to consider
closed terms without parameters.
We thus define strict terms (sterms) are terms without constants
Inductive sterm : @trm X -> Prop :=
| sterm_var : forall a, sterm (trm_fvar a)
| sterm_abs : forall L t,
(forall a, a\notin L -> sterm (open_rec_trm 0 t (trm_fvar a))) ->
sterm (trm_abs t)
| sterm_app : ∀ t u, sterm t → sterm u → sterm (trm_app t u)
| sterm_cc : sterm trm_cc
.
Hint Resolve term_var term_abs term_app term_cc.
Hint Resolve sterm_var sterm_abs sterm_app sterm_cc.
Lemma sterm_term: ∀t, sterm t → term t.
Proof.
intros t H; induction H; auto.
apply term_abs with L0;trivial.
Qed.
Definition sclosed (t:trm):= sterm t ∧ fv_trm t = \{}.
| sterm_var : forall a, sterm (trm_fvar a)
| sterm_abs : forall L t,
(forall a, a\notin L -> sterm (open_rec_trm 0 t (trm_fvar a))) ->
sterm (trm_abs t)
| sterm_app : ∀ t u, sterm t → sterm u → sterm (trm_app t u)
| sterm_cc : sterm trm_cc
.
Hint Resolve term_var term_abs term_app term_cc.
Hint Resolve sterm_var sterm_abs sterm_app sterm_cc.
Lemma sterm_term: ∀t, sterm t → term t.
Proof.
intros t H; induction H; auto.
apply term_abs with L0;trivial.
Qed.
Definition sclosed (t:trm):= sterm t ∧ fv_trm t = \{}.
This is our only axiom, to avoid the definition of the compilation functions
from λ-terms to combinator. It simply states the well-known fact that any
closed λ-term can be expressed as a combination of K and S modulo ß-reduction.
Observe that we consider here λc-term, i.e. λ-terms extended with call/cc,
and consequently the combinatorial basis K,S,cc. Since we didn't give reduction
rules to call/cc, it plays the role of an inert constant and it is obvious that
it doesn't affect the result.
Axiom combinatory_completeness:
∀ t, sclosed t → ∃ c, betared (trm_comb c) t.
Lemma combinator_trm_translated:
∀ t a, sclosed t → translated t a → ∃ c, (combinator c ∧ c ≤ a).
Proof.
intros t a Ht Tr.
destruct (combinatory_completeness Ht) as (c,Beta).
exists (imp_comb c);split.
+ apply combinator_comb.
+ apply (imp_betared (translated_comb _) Tr Beta).
Qed.
End Combinators.