Rocoma.Recipes_box_rel
TODO move this
Ltac ty_beta_tac U :=
apply has_type_beta_gen with U=>//;
first [ apply closed_box
| apply closedh_box
| constructor ].
apply has_type_beta_gen with U=>//;
first [ apply closed_box
| apply closedh_box
| constructor ].
box_rel P r holds when the logrel-extension of P holds strongly on every
directly boxed subrecipe of r. Only box_rel_box carries a type: that is
where logrel P U needs one, and has_type_det makes it unique.
Inductive box_rel P : recipe -> Prop :=
| box_rel_box s U :
closed s ->
[ ⊢ s :- U ] ->
(forall ξ, strongly (logrel P U) s.|[ren ξ]) ->
box_rel P (Box s)
| box_rel_tlam s : box_rel P s -> box_rel P (TLam s)
| box_rel_tall s : box_rel P s -> box_rel P (TAll s)
| box_rel_neu s : box_rel P s -> box_rel P (Neu s)
| box_rel_imp s f : box_rel P s -> box_rel P (Imp s f)
| box_rel_lam s U : box_rel P s -> box_rel P (Lam s U)
| box_rel_tapp s T : box_rel P s -> box_rel P (TApp s T)
| box_rel_var x : box_rel P (Var x)
| box_rel_top : box_rel P Top
| box_rel_zero : box_rel P Zero
| box_rel_app s t : box_rel P s -> box_rel P t -> box_rel P (App s t)
| box_rel_and s t : box_rel P s -> box_rel P t -> box_rel P (And s t).
Lemma box_rel_preserved_subst P :
forall s n U t,
closed t ->
[ ⊢ t :- U ] ->
(forall ξ, strongly (logrel P U) t.|[ren ξ]) ->
box_rel P s ->
box_rel P s.[Box t//n].
Proof.
elim=>//=.
- move=> x n U t hc ht hst _.
rewrite /subst_var.
(* the box is created here *)
case (lt_eq_lt_dec x n)=> [[]|] hn; try by apply box_rel_var.
by apply box_rel_box with U.
(* Zero and Top are discharged by the // of elim *)
- move=> > hs > ht > ??? hb.
inv hb.
by constructor; eauto.
- move=> > hs > ht > ??? hb.
inv hb.
by constructor; eauto.
- move=> > hs > ??? hb.
inv hb.
by constructor; eauto.
- move=> s hs W n U u ??? hb.
inv hb.
rewrite upn1 subst_var_lemma.
have->: (Box u).[ren (+1)] = Box u by apply closed_subst, closed_box.
by constructor; eauto.
- move=> > hs > ??? hb.
inv hb.
by constructor; eauto.
- move=> s hs n U u hcu htu hsu hb.
inv hb.
(* the box travels under the binder, so its content is shifted *)
rewrite subst_var_hsubst /=.
constructor; apply hs with U=> [||θ|]; last by [].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl; apply hsu.
- move=> s hs n U u hcu htu hsu hb.
inv hb.
rewrite subst_var_hsubst /=.
constructor; apply hs with U=> [||θ|]; last by [].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl; apply hsu.
- move=> > hs > ??? hb.
inv hb.
by constructor; eauto.
- move=> s hs n U u ??? hb.
inv hb.
(* the substitution does not enter a box: its content is closed *)
rewrite closed_subst=>//.
by apply box_rel_box with U0.
Qed.
Corollary box_rel_preserved_subst0 P s U t :
closed t ->
[ ⊢ t :- U ] ->
(forall ξ, strongly (logrel P U) t.|[ren ξ]) ->
box_rel P s ->
box_rel P s.[Box t/].
Proof.
move=> *.
have:= @box_rel_preserved_subst P s 0 U t.
rewrite -subst_var_0.
by apply.
Qed.
Lemma up_ren_term (ζ : var -> var) :
(up (ren ζ) : var -> term) = ren (upren ζ).
Proof. f_ext. by case=> [|y]; asimpl. Qed.
Lemma box_rel_preserved_ren P s ξ :
box_rel P s ->
box_rel P s.|[ren ξ].
Proof.
elim: s ξ
=> [x|||s hs t ht|s hs t ht|s hs S|s hs W|s hs f|s hs|s hs|s hs|s hs] ξ hb /=;
try (by constructor);
try (by inv hb; constructor; eauto).
- by rewrite up_ren_term; inv hb; apply box_rel_tlam; apply hs.
- by rewrite up_ren_term; inv hb; apply box_rel_tall; apply hs.
- inv hb.
apply box_rel_box with U=> [||ξ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
Qed.
a term substitution only reaches a box as a renaming, hsubst_T_is_ren
Lemma box_rel_preserved_hsubst P r Γ U a b d T :
d < b ->
[ Γ, a, b ⊢ r :- U ] ->
box_rel P r ->
box_rel P r.|[upn d (T .: ids)].
Proof.
elim: r Γ U a b d=>/=.
- by move=> *; apply box_rel_var.
- by move=> *; apply box_rel_zero.
- by move=> *; apply box_rel_top.
- move=> s h1 t h2 Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_and; [apply h1 with Γ U a b|apply h2 with Γ U a b].
- move=> s h1 t h2 Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_app; [apply h1 with Γ (Arr U0 U) a b|apply h2 with Γ U0 a b].
- move=> s h1 S Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_tapp; apply h1 with Γ (TArr U) a b.
- move=> s h1 W Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_lam; apply h1 with (W .: Γ) V a b.
- move=> s h1 f Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_imp; apply h1 with Γ Void a b.
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
rewrite fold_up_upn.
by apply box_rel_tlam; apply h1 with Γ U0 a.+1 b.+1; [lia| |].
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
rewrite fold_up_upn.
by apply box_rel_tall; apply h1 with Γ Void a.+1 b.+1; [lia| |].
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_neu; apply h1 with Γ U a b.
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
rewrite (hsubst_T_is_ren (Γ:=Γ) (U:=U) (a:=0) (b:=b))=>//.
apply box_rel_box with U0=> [||ξ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
Qed.
Corollary box_rel_preserved_hsubst0 P r Γ U a b T :
1 <= b ->
[ Γ, a, b ⊢ r :- U ] ->
box_rel P r ->
box_rel P r.|[T/].
Proof.
move=> hb hty h.
have:= @box_rel_preserved_hsubst P r Γ U a b 0 T.
rewrite upn0. by apply.
Qed.
Lemma box_rel_preserved_neu P s :
box_rel P s ->
box_rel P (neu s).
Proof.
elim=>{s}//=; try by constructor.
move=> s U hc ht h.
apply box_rel_box with U.
- by apply closed_sneu.
- by apply has_type_neu.
- move=> θ; rewrite -neu_hsubst_comm.
have[??]:= h θ.
by split; rewrite ?neu_idempotent.
Qed.
Lemma unfold_box_rel P r Γ U a b :
[ Γ, a, b ⊢ r :- U ] ->
(forall s V, directly_box s r -> [ ⊢ s :- V ] ->
forall ξ, strongly (logrel P V) s.|[ren ξ]) ->
box_rel P r.
Proof.
elim: r Γ U a b.
- by move=> *; constructor.
- by move=> *; constructor.
- by move=> *; constructor.
- move=> s hs t ht Γ U a b hty ih.
constructor.
+ apply hs with Γ U a b; first by inv hty.
move=> > hdb. apply: ih. by left.
+ apply ht with Γ U a b; first by inv hty.
move=> > hdb. apply: ih. by right.
- move=> s hs t ht Γ U a b hty ih.
have[W [hs1 ht1]]:
exists W, [ Γ, a, b ⊢ s :- Arr W U ] /\ [ Γ, a, b ⊢ t :- W ]
by inv hty; eauto.
constructor.
+ apply hs with Γ (Arr W U) a b; first by [].
move=> > hdb. apply: ih. by left.
+ apply ht with Γ W a b; first by [].
move=> > hdb. apply: ih. by right.
- move=> s hs T Γ U a b hty ih.
constructor.
apply hs with Γ (TArr U) a b; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs W Γ U a b hty ih.
have[V hs1]: exists V, [ W .: Γ, a, b ⊢ s :- V ] by inv hty; eauto.
constructor.
apply hs with (W .: Γ) V a b; first by [].
by move=> > hdb; apply: ih.
- move=> s hs f Γ U a b hty ih.
constructor.
apply hs with Γ U a b; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
have[V hs1]: exists V, [ Γ, a.+1, b.+1 ⊢ s :- V ] by inv hty; eauto.
constructor.
apply hs with Γ V a.+1 b.+1; first by [].
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
constructor.
apply hs with Γ U a.+1 b.+1; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
constructor.
apply hs with Γ U a b; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
inv hty.
have hts: [ ⊢ s :- U ].
{ apply (has_type_lower_b (b:=b))=>//.
by apply closed_has_ty_contr with Γ. }
have?: forall ξ, strongly (logrel P U) s.|[ren ξ] by apply ih.
by apply box_rel_box with U.
Qed.
Lemma box_rel_box_ids P s :
box_rel P (Box s) ->
exists U, closed s /\ [ ⊢ s :- U ] /\ strongly (logrel P U) s.
Proof.
move=> h; inv h.
exists U; split=>//; split=>//.
have hh: strongly (logrel P U) s.|[ids] by apply H2.
by asimpl in hh.
Qed.
Lemma box_rel_nobox P s :
~ mem_box s -> box_rel P s.
Proof.
elim: s
=> [x|||s hs t ht|s hs t ht|s hs S|s hs W|s hs f|s hs|s hs|s hs|s hs] /= h;
try by constructor.
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by exfalso; apply h.
Qed.
(* Relation R strongly holds on the recipes bellow boxes .... TODO *)
d < b ->
[ Γ, a, b ⊢ r :- U ] ->
box_rel P r ->
box_rel P r.|[upn d (T .: ids)].
Proof.
elim: r Γ U a b d=>/=.
- by move=> *; apply box_rel_var.
- by move=> *; apply box_rel_zero.
- by move=> *; apply box_rel_top.
- move=> s h1 t h2 Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_and; [apply h1 with Γ U a b|apply h2 with Γ U a b].
- move=> s h1 t h2 Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_app; [apply h1 with Γ (Arr U0 U) a b|apply h2 with Γ U0 a b].
- move=> s h1 S Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_tapp; apply h1 with Γ (TArr U) a b.
- move=> s h1 W Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_lam; apply h1 with (W .: Γ) V a b.
- move=> s h1 f Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_imp; apply h1 with Γ Void a b.
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
rewrite fold_up_upn.
by apply box_rel_tlam; apply h1 with Γ U0 a.+1 b.+1; [lia| |].
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
rewrite fold_up_upn.
by apply box_rel_tall; apply h1 with Γ Void a.+1 b.+1; [lia| |].
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
by apply box_rel_neu; apply h1 with Γ U a b.
- move=> s h1 Γ U a b d hdb hty hb; inv hty; inv hb.
rewrite (hsubst_T_is_ren (Γ:=Γ) (U:=U) (a:=0) (b:=b))=>//.
apply box_rel_box with U0=> [||ξ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
Qed.
Corollary box_rel_preserved_hsubst0 P r Γ U a b T :
1 <= b ->
[ Γ, a, b ⊢ r :- U ] ->
box_rel P r ->
box_rel P r.|[T/].
Proof.
move=> hb hty h.
have:= @box_rel_preserved_hsubst P r Γ U a b 0 T.
rewrite upn0. by apply.
Qed.
Lemma box_rel_preserved_neu P s :
box_rel P s ->
box_rel P (neu s).
Proof.
elim=>{s}//=; try by constructor.
move=> s U hc ht h.
apply box_rel_box with U.
- by apply closed_sneu.
- by apply has_type_neu.
- move=> θ; rewrite -neu_hsubst_comm.
have[??]:= h θ.
by split; rewrite ?neu_idempotent.
Qed.
Lemma unfold_box_rel P r Γ U a b :
[ Γ, a, b ⊢ r :- U ] ->
(forall s V, directly_box s r -> [ ⊢ s :- V ] ->
forall ξ, strongly (logrel P V) s.|[ren ξ]) ->
box_rel P r.
Proof.
elim: r Γ U a b.
- by move=> *; constructor.
- by move=> *; constructor.
- by move=> *; constructor.
- move=> s hs t ht Γ U a b hty ih.
constructor.
+ apply hs with Γ U a b; first by inv hty.
move=> > hdb. apply: ih. by left.
+ apply ht with Γ U a b; first by inv hty.
move=> > hdb. apply: ih. by right.
- move=> s hs t ht Γ U a b hty ih.
have[W [hs1 ht1]]:
exists W, [ Γ, a, b ⊢ s :- Arr W U ] /\ [ Γ, a, b ⊢ t :- W ]
by inv hty; eauto.
constructor.
+ apply hs with Γ (Arr W U) a b; first by [].
move=> > hdb. apply: ih. by left.
+ apply ht with Γ W a b; first by [].
move=> > hdb. apply: ih. by right.
- move=> s hs T Γ U a b hty ih.
constructor.
apply hs with Γ (TArr U) a b; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs W Γ U a b hty ih.
have[V hs1]: exists V, [ W .: Γ, a, b ⊢ s :- V ] by inv hty; eauto.
constructor.
apply hs with (W .: Γ) V a b; first by [].
by move=> > hdb; apply: ih.
- move=> s hs f Γ U a b hty ih.
constructor.
apply hs with Γ U a b; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
have[V hs1]: exists V, [ Γ, a.+1, b.+1 ⊢ s :- V ] by inv hty; eauto.
constructor.
apply hs with Γ V a.+1 b.+1; first by [].
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
constructor.
apply hs with Γ U a.+1 b.+1; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
constructor.
apply hs with Γ U a b; first by inv hty.
by move=> > hdb; apply: ih.
- move=> s hs Γ U a b hty ih.
inv hty.
have hts: [ ⊢ s :- U ].
{ apply (has_type_lower_b (b:=b))=>//.
by apply closed_has_ty_contr with Γ. }
have?: forall ξ, strongly (logrel P U) s.|[ren ξ] by apply ih.
by apply box_rel_box with U.
Qed.
Lemma box_rel_box_ids P s :
box_rel P (Box s) ->
exists U, closed s /\ [ ⊢ s :- U ] /\ strongly (logrel P U) s.
Proof.
move=> h; inv h.
exists U; split=>//; split=>//.
have hh: strongly (logrel P U) s.|[ids] by apply H2.
by asimpl in hh.
Qed.
Lemma box_rel_nobox P s :
~ mem_box s -> box_rel P s.
Proof.
elim: s
=> [x|||s hs t ht|s hs t ht|s hs S|s hs W|s hs f|s hs|s hs|s hs|s hs] /= h;
try by constructor.
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by exfalso; apply h.
Qed.
(* Relation R strongly holds on the recipes bellow boxes .... TODO *)
Same shape as box_rel, for a pair of recipes.
Inductive box_rel2 P : recipe -> recipe -> Prop :=
| box_rel2_box s t U :
closed s -> [ ⊢ s :- U ] ->
closed t -> [ ⊢ t :- U ] ->
(forall ξ, strongly2 (logrel2 P U) s.|[ren ξ] t.|[ren ξ]) ->
box_rel2 P (Box s) (Box t)
| box_rel2_tlam s t : box_rel2 P s t -> box_rel2 P (TLam s) (TLam t)
| box_rel2_tall s t : box_rel2 P s t -> box_rel2 P (TAll s) (TAll t)
| box_rel2_neu s t : box_rel2 P s t -> box_rel2 P (Neu s) (Neu t)
| box_rel2_imp s t f : box_rel2 P s t -> box_rel2 P (Imp s f) (Imp t f)
| box_rel2_lam s t U : box_rel2 P s t -> box_rel2 P (Lam s U) (Lam t U)
| box_rel2_tapp s t T : box_rel2 P s t -> box_rel2 P (TApp s T) (TApp t T)
| box_rel2_var x : box_rel2 P (Var x) (Var x)
| box_rel2_top : box_rel2 P Top Top
| box_rel2_zero : box_rel2 P Zero Zero
| box_rel2_app s1 t1 s2 t2 :
box_rel2 P s1 s2 -> box_rel2 P t1 t2 -> box_rel2 P (App s1 t1) (App s2 t2)
| box_rel2_and s1 t1 s2 t2 :
box_rel2 P s1 s2 -> box_rel2 P t1 t2 -> box_rel2 P (And s1 t1) (And s2 t2).
Lemma box_rel2_weight_eq P s t :
box_rel2 P s t -> weight s = weight t.
Proof.
by elim=>//=; eauto.
Qed.
Lemma box_rel2_preserved_neu P s t :
box_rel2 P s t ->
box_rel2 P (neu s) (neu t).
Proof.
elim=>{s t}//=; try by constructor.
move=> s t U hc1 ht1 hc2 ht2 h.
apply box_rel2_box with U.
- by apply closed_sneu.
- by apply has_type_neu.
- by apply closed_sneu.
- by apply has_type_neu.
- move=> θ; rewrite -!neu_hsubst_comm.
have[??]:= h θ.
by split; rewrite ?neu_idempotent.
Qed.
Lemma box_rel2_preserved_subst P s t u v U :
closed u -> [ ⊢ u :- U ] ->
closed v -> [ ⊢ v :- U ] ->
(forall ξ, strongly2 (logrel2 P U) u.|[ren ξ] v.|[ren ξ]) ->
box_rel2 P s t ->
forall n, box_rel2 P s.[Box u//n] t.[Box v//n].
Proof.
move=> hcu htu hcv htv hst hb.
move: u v hcu htu hcv htv hst.
elim: hb=>{s t}.
- move=> s t W hc1 ht1 hc2 ht2 hs u v hcu htu hcv htv hst n /=.
(* the substitution does not enter a box *)
have->: s.[subst_var (Box u) n] = s by apply closed_subst.
have->: t.[subst_var (Box v) n] = t by apply closed_subst.
by apply box_rel2_box with W.
- move=> s t _ ih u v hcu htu hcv htv hst n /=.
(* the boxes travel under the binder, so their contents are shifted *)
rewrite !subst_var_hsubst /=.
apply box_rel2_tlam; apply ih.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by move=> θ; asimpl; apply hst.
- move=> s t _ ih u v hcu htu hcv htv hst n /=.
rewrite !subst_var_hsubst /=.
apply box_rel2_tall; apply ih.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by move=> θ; asimpl; apply hst.
- move=> s t _ ih u v hcu htu hcv htv hst n /=.
apply box_rel2_neu.
by apply ih.
- move=> s t f _ ih u v hcu htu hcv htv hst n /=.
apply box_rel2_imp.
by apply ih.
- move=> s t W _ ih u v hcu htu hcv htv hst n /=.
rewrite upn1 !subst_var_lemma.
have->: (Box u).[ren (+1)] = Box u by apply closed_subst, closed_box.
have->: (Box v).[ren (+1)] = Box v by apply closed_subst, closed_box.
apply box_rel2_lam. by apply ih.
- move=> s t T _ ih u v hcu htu hcv htv hst n /=.
apply box_rel2_tapp.
by apply ih.
- move=> x u v hcu htu hcv htv hst n /=.
rewrite /subst_var.
case (lt_eq_lt_dec x n)=> [[]|] hn; try by apply box_rel2_var.
by apply box_rel2_box with U.
- by move=> *; apply box_rel2_top.
- by move=> *; apply box_rel2_zero.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 u v hcu htu hcv htv hst n /=.
apply box_rel2_app; by [apply ih1 | apply ih2].
- move=> s1 t1 s2 t2 _ ih1 _ ih2 u v hcu htu hcv htv hst n /=.
apply box_rel2_and; by [apply ih1 | apply ih2].
Qed.
Corollary box_rel2_preserved_subst0 P s t u v U :
closed u -> [ ⊢ u :- U ] ->
closed v -> [ ⊢ v :- U ] ->
(forall ξ, strongly2 (logrel2 P U) u.|[ren ξ] v.|[ren ξ]) ->
box_rel2 P s t ->
box_rel2 P s.[Box u/] t.[Box v/].
Proof.
move=> *.
have:= @box_rel2_preserved_subst P s t u v U.
rewrite -!subst_var_0.
by apply.
Qed.
Lemma box_rel2_preserved_ren P s t :
box_rel2 P s t ->
forall ξ, box_rel2 P s.|[ren ξ] t.|[ren ξ].
Proof.
elim=>{s t}.
- move=> s t U hc1 ht1 hc2 ht2 hs θ /=.
apply box_rel2_box with U=> [||||θ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
- move=> s t _ ih θ /=.
rewrite !up_ren_term.
apply box_rel2_tlam.
by apply ih.
- move=> s t _ ih θ /=.
rewrite !up_ren_term.
apply box_rel2_tall.
by apply ih.
- move=> s t _ ih θ /=. apply box_rel2_neu. by apply ih.
- move=> s t f _ ih θ /=. apply box_rel2_imp. by apply ih.
- move=> s t U _ ih θ /=. apply box_rel2_lam. by apply ih.
- move=> s t T _ ih θ /=. apply box_rel2_tapp. by apply ih.
- by move=> x θ /=; apply box_rel2_var.
- by move=> θ /=; apply box_rel2_top.
- by move=> θ /=; apply box_rel2_zero.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 θ /=.
apply box_rel2_app; by [apply ih1 | apply ih2].
- move=> s1 t1 s2 t2 _ ih1 _ ih2 θ /=.
apply box_rel2_and; by [apply ih1 | apply ih2].
Qed.
Lemma box_rel2_preserved_hsubst P r1 r2 Γ U1 U2 a b d T :
d < b ->
[ Γ, a, b ⊢ r1 :- U1 ] -> [ Γ, a, b ⊢ r2 :- U2 ] ->
box_rel2 P r1 r2 ->
box_rel2 P r1.|[upn d (T .: ids)] r2.|[upn d (T .: ids)].
Proof.
move=> hdb ht1 ht2 hb.
move: hb Γ U1 U2 a b d hdb ht1 ht2.
elim=>{r1 r2}.
- move=> s t V hcs hts hct htt hst Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
rewrite (hsubst_T_is_ren (Γ:=Γ) (U:=U1) (a:=0) (b:=b) (s:=s))=>//.
rewrite (hsubst_T_is_ren (Γ:=Γ) (U:=U2) (a:=0) (b:=b) (s:=t))=>//.
apply box_rel2_box with V=> [||||ξ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
- move=> s t _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
rewrite !fold_up_upn.
apply box_rel2_tlam.
apply ih with Γ U U0 a.+1 b.+1=>//.
- move=> s t _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
rewrite !fold_up_upn.
apply box_rel2_tall.
apply ih with Γ Void Void a.+1 b.+1=>//.
- move=> s t _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_neu.
by apply ih with Γ U1 U2 a b.
- move=> s t f _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_imp.
by apply ih with Γ Void Void a b.
- move=> s t W _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_lam.
by apply ih with (W .: Γ) V V0 a b.
- move=> s t S _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_tapp.
by apply ih with Γ (TArr U1) (TArr U2) a b.
- by move=> *; apply box_rel2_var.
- by move=> *; apply box_rel2_top.
- by move=> *; apply box_rel2_zero.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_app; by [apply ih1 with Γ (Arr U U1) (Arr U0 U2) a b|apply ih2 with Γ U U0 a b].
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_and; by [apply ih1 with Γ U1 U2 a b|apply ih2 with Γ U1 U2 a b].
Qed.
Corollary box_rel2_preserved_hsubst0 P r1 r2 Γ U1 U2 a b T :
1 <= b ->
[ Γ, a, b ⊢ r1 :- U1 ] -> [ Γ, a, b ⊢ r2 :- U2 ] ->
box_rel2 P r1 r2 ->
box_rel2 P r1.|[T/] r2.|[T/].
Proof.
move=> hb ht1 ht2 h.
have:= @box_rel2_preserved_hsubst P r1 r2 Γ U1 U2 a b 0 T.
rewrite upn0. by apply.
Qed.
| box_rel2_box s t U :
closed s -> [ ⊢ s :- U ] ->
closed t -> [ ⊢ t :- U ] ->
(forall ξ, strongly2 (logrel2 P U) s.|[ren ξ] t.|[ren ξ]) ->
box_rel2 P (Box s) (Box t)
| box_rel2_tlam s t : box_rel2 P s t -> box_rel2 P (TLam s) (TLam t)
| box_rel2_tall s t : box_rel2 P s t -> box_rel2 P (TAll s) (TAll t)
| box_rel2_neu s t : box_rel2 P s t -> box_rel2 P (Neu s) (Neu t)
| box_rel2_imp s t f : box_rel2 P s t -> box_rel2 P (Imp s f) (Imp t f)
| box_rel2_lam s t U : box_rel2 P s t -> box_rel2 P (Lam s U) (Lam t U)
| box_rel2_tapp s t T : box_rel2 P s t -> box_rel2 P (TApp s T) (TApp t T)
| box_rel2_var x : box_rel2 P (Var x) (Var x)
| box_rel2_top : box_rel2 P Top Top
| box_rel2_zero : box_rel2 P Zero Zero
| box_rel2_app s1 t1 s2 t2 :
box_rel2 P s1 s2 -> box_rel2 P t1 t2 -> box_rel2 P (App s1 t1) (App s2 t2)
| box_rel2_and s1 t1 s2 t2 :
box_rel2 P s1 s2 -> box_rel2 P t1 t2 -> box_rel2 P (And s1 t1) (And s2 t2).
Lemma box_rel2_weight_eq P s t :
box_rel2 P s t -> weight s = weight t.
Proof.
by elim=>//=; eauto.
Qed.
Lemma box_rel2_preserved_neu P s t :
box_rel2 P s t ->
box_rel2 P (neu s) (neu t).
Proof.
elim=>{s t}//=; try by constructor.
move=> s t U hc1 ht1 hc2 ht2 h.
apply box_rel2_box with U.
- by apply closed_sneu.
- by apply has_type_neu.
- by apply closed_sneu.
- by apply has_type_neu.
- move=> θ; rewrite -!neu_hsubst_comm.
have[??]:= h θ.
by split; rewrite ?neu_idempotent.
Qed.
Lemma box_rel2_preserved_subst P s t u v U :
closed u -> [ ⊢ u :- U ] ->
closed v -> [ ⊢ v :- U ] ->
(forall ξ, strongly2 (logrel2 P U) u.|[ren ξ] v.|[ren ξ]) ->
box_rel2 P s t ->
forall n, box_rel2 P s.[Box u//n] t.[Box v//n].
Proof.
move=> hcu htu hcv htv hst hb.
move: u v hcu htu hcv htv hst.
elim: hb=>{s t}.
- move=> s t W hc1 ht1 hc2 ht2 hs u v hcu htu hcv htv hst n /=.
(* the substitution does not enter a box *)
have->: s.[subst_var (Box u) n] = s by apply closed_subst.
have->: t.[subst_var (Box v) n] = t by apply closed_subst.
by apply box_rel2_box with W.
- move=> s t _ ih u v hcu htu hcv htv hst n /=.
(* the boxes travel under the binder, so their contents are shifted *)
rewrite !subst_var_hsubst /=.
apply box_rel2_tlam; apply ih.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by move=> θ; asimpl; apply hst.
- move=> s t _ ih u v hcu htu hcv htv hst n /=.
rewrite !subst_var_hsubst /=.
apply box_rel2_tall; apply ih.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by move=> θ; asimpl; apply hst.
- move=> s t _ ih u v hcu htu hcv htv hst n /=.
apply box_rel2_neu.
by apply ih.
- move=> s t f _ ih u v hcu htu hcv htv hst n /=.
apply box_rel2_imp.
by apply ih.
- move=> s t W _ ih u v hcu htu hcv htv hst n /=.
rewrite upn1 !subst_var_lemma.
have->: (Box u).[ren (+1)] = Box u by apply closed_subst, closed_box.
have->: (Box v).[ren (+1)] = Box v by apply closed_subst, closed_box.
apply box_rel2_lam. by apply ih.
- move=> s t T _ ih u v hcu htu hcv htv hst n /=.
apply box_rel2_tapp.
by apply ih.
- move=> x u v hcu htu hcv htv hst n /=.
rewrite /subst_var.
case (lt_eq_lt_dec x n)=> [[]|] hn; try by apply box_rel2_var.
by apply box_rel2_box with U.
- by move=> *; apply box_rel2_top.
- by move=> *; apply box_rel2_zero.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 u v hcu htu hcv htv hst n /=.
apply box_rel2_app; by [apply ih1 | apply ih2].
- move=> s1 t1 s2 t2 _ ih1 _ ih2 u v hcu htu hcv htv hst n /=.
apply box_rel2_and; by [apply ih1 | apply ih2].
Qed.
Corollary box_rel2_preserved_subst0 P s t u v U :
closed u -> [ ⊢ u :- U ] ->
closed v -> [ ⊢ v :- U ] ->
(forall ξ, strongly2 (logrel2 P U) u.|[ren ξ] v.|[ren ξ]) ->
box_rel2 P s t ->
box_rel2 P s.[Box u/] t.[Box v/].
Proof.
move=> *.
have:= @box_rel2_preserved_subst P s t u v U.
rewrite -!subst_var_0.
by apply.
Qed.
Lemma box_rel2_preserved_ren P s t :
box_rel2 P s t ->
forall ξ, box_rel2 P s.|[ren ξ] t.|[ren ξ].
Proof.
elim=>{s t}.
- move=> s t U hc1 ht1 hc2 ht2 hs θ /=.
apply box_rel2_box with U=> [||||θ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
- move=> s t _ ih θ /=.
rewrite !up_ren_term.
apply box_rel2_tlam.
by apply ih.
- move=> s t _ ih θ /=.
rewrite !up_ren_term.
apply box_rel2_tall.
by apply ih.
- move=> s t _ ih θ /=. apply box_rel2_neu. by apply ih.
- move=> s t f _ ih θ /=. apply box_rel2_imp. by apply ih.
- move=> s t U _ ih θ /=. apply box_rel2_lam. by apply ih.
- move=> s t T _ ih θ /=. apply box_rel2_tapp. by apply ih.
- by move=> x θ /=; apply box_rel2_var.
- by move=> θ /=; apply box_rel2_top.
- by move=> θ /=; apply box_rel2_zero.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 θ /=.
apply box_rel2_app; by [apply ih1 | apply ih2].
- move=> s1 t1 s2 t2 _ ih1 _ ih2 θ /=.
apply box_rel2_and; by [apply ih1 | apply ih2].
Qed.
Lemma box_rel2_preserved_hsubst P r1 r2 Γ U1 U2 a b d T :
d < b ->
[ Γ, a, b ⊢ r1 :- U1 ] -> [ Γ, a, b ⊢ r2 :- U2 ] ->
box_rel2 P r1 r2 ->
box_rel2 P r1.|[upn d (T .: ids)] r2.|[upn d (T .: ids)].
Proof.
move=> hdb ht1 ht2 hb.
move: hb Γ U1 U2 a b d hdb ht1 ht2.
elim=>{r1 r2}.
- move=> s t V hcs hts hct htt hst Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
rewrite (hsubst_T_is_ren (Γ:=Γ) (U:=U1) (a:=0) (b:=b) (s:=s))=>//.
rewrite (hsubst_T_is_ren (Γ:=Γ) (U:=U2) (a:=0) (b:=b) (s:=t))=>//.
apply box_rel2_box with V=> [||||ξ'].
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by apply closed_unaffectedh.
+ by apply has_type_hsubst_0.
+ by asimpl.
- move=> s t _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
rewrite !fold_up_upn.
apply box_rel2_tlam.
apply ih with Γ U U0 a.+1 b.+1=>//.
- move=> s t _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
rewrite !fold_up_upn.
apply box_rel2_tall.
apply ih with Γ Void Void a.+1 b.+1=>//.
- move=> s t _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_neu.
by apply ih with Γ U1 U2 a b.
- move=> s t f _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_imp.
by apply ih with Γ Void Void a b.
- move=> s t W _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_lam.
by apply ih with (W .: Γ) V V0 a b.
- move=> s t S _ ih Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_tapp.
by apply ih with Γ (TArr U1) (TArr U2) a b.
- by move=> *; apply box_rel2_var.
- by move=> *; apply box_rel2_top.
- by move=> *; apply box_rel2_zero.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_app; by [apply ih1 with Γ (Arr U U1) (Arr U0 U2) a b|apply ih2 with Γ U U0 a b].
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b d hdb ht1 ht2 /=.
inv ht1.
inv ht2.
apply box_rel2_and; by [apply ih1 with Γ U1 U2 a b|apply ih2 with Γ U1 U2 a b].
Qed.
Corollary box_rel2_preserved_hsubst0 P r1 r2 Γ U1 U2 a b T :
1 <= b ->
[ Γ, a, b ⊢ r1 :- U1 ] -> [ Γ, a, b ⊢ r2 :- U2 ] ->
box_rel2 P r1 r2 ->
box_rel2 P r1.|[T/] r2.|[T/].
Proof.
move=> hb ht1 ht2 h.
have:= @box_rel2_preserved_hsubst P r1 r2 Γ U1 U2 a b 0 T.
rewrite upn0. by apply.
Qed.
Two recipes of the same shape typed in the same context have the same type.
Lemma box_rel2_type_det P s t Γ U1 U2 a b :
box_rel2 P s t ->
[ Γ, a, b ⊢ s :- U1 ] -> [ Γ, a, b ⊢ t :- U2 ] ->
U1 = U2.
Proof.
move=> hb.
move: Γ U1 U2 a b.
elim: hb=>{s t}.
- move=> s t V hcs hts hct htt _ Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
have e1: U1 = V.
{ apply has_type_det with empty_ctx 0 0 s=>//.
apply (has_type_lower_b (b:=b))=>//.
by apply closed_has_ty_contr with Γ. }
have e2: U2 = V.
{ apply has_type_det with empty_ctx 0 0 t=>//.
apply (has_type_lower_b (b:=b))=>//.
by apply closed_has_ty_contr with Γ. }
by rewrite e1 e2.
- move=> s t _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
f_equal.
by apply ih with (Γ:=Γ) (a:=a.+1) (b:=b.+1).
- by move=> s t _ ih Γ U1 U2 a b h1 h2; inv h1; inv h2.
- move=> s t _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
by apply ih with (Γ:=Γ) (a:=a) (b:=b).
- by move=> s t f _ ih Γ U1 U2 a b h1 h2; inv h1; inv h2.
- move=> s t W _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
f_equal.
by apply ih with (Γ:=W .: Γ) (a:=a) (b:=b).
- move=> s t S _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
have e: TArr U1 = TArr U2 by apply ih with (Γ:=Γ) (a:=a) (b:=b).
by inv e.
- by move=> x Γ U1 U2 a b h1 h2; inv h1; inv h2.
- by move=> Γ U1 U2 a b h1 h2; inv h1; inv h2.
- by move=> Γ U1 U2 a b h1 h2; inv h1; inv h2.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
have e: Arr U U1 = Arr U0 U2 by apply ih1 with (Γ:=Γ) (a:=a) (b:=b).
by inv e.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
by apply ih1 with (Γ:=Γ) (a:=a) (b:=b).
Qed.
Lemma box_rel2_box_ids P s t :
box_rel2 P (Box s) (Box t) ->
exists U, closed s /\ [ ⊢ s :- U ] /\
closed t /\ [ ⊢ t :- U ] /\
strongly2 (logrel2 P U) s t.
Proof.
move=> h; inv h.
exists U; do 4 (split=>//).
have hh: strongly2 (logrel2 P U) s.|[ids] t.|[ids] by apply H5.
by asimpl in hh.
Qed.
Lemma box_rel2_nobox P s :
~ mem_box s -> box_rel2 P s s.
Proof.
elim: s
=> [x|||s hs t ht|s hs t ht|s hs S|s hs W|s hs f|s hs|s hs|s hs|s hs] /= h;
try by constructor.
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by exfalso; apply h.
Qed.
box_rel2 P s t ->
[ Γ, a, b ⊢ s :- U1 ] -> [ Γ, a, b ⊢ t :- U2 ] ->
U1 = U2.
Proof.
move=> hb.
move: Γ U1 U2 a b.
elim: hb=>{s t}.
- move=> s t V hcs hts hct htt _ Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
have e1: U1 = V.
{ apply has_type_det with empty_ctx 0 0 s=>//.
apply (has_type_lower_b (b:=b))=>//.
by apply closed_has_ty_contr with Γ. }
have e2: U2 = V.
{ apply has_type_det with empty_ctx 0 0 t=>//.
apply (has_type_lower_b (b:=b))=>//.
by apply closed_has_ty_contr with Γ. }
by rewrite e1 e2.
- move=> s t _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
f_equal.
by apply ih with (Γ:=Γ) (a:=a.+1) (b:=b.+1).
- by move=> s t _ ih Γ U1 U2 a b h1 h2; inv h1; inv h2.
- move=> s t _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
by apply ih with (Γ:=Γ) (a:=a) (b:=b).
- by move=> s t f _ ih Γ U1 U2 a b h1 h2; inv h1; inv h2.
- move=> s t W _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
f_equal.
by apply ih with (Γ:=W .: Γ) (a:=a) (b:=b).
- move=> s t S _ ih Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
have e: TArr U1 = TArr U2 by apply ih with (Γ:=Γ) (a:=a) (b:=b).
by inv e.
- by move=> x Γ U1 U2 a b h1 h2; inv h1; inv h2.
- by move=> Γ U1 U2 a b h1 h2; inv h1; inv h2.
- by move=> Γ U1 U2 a b h1 h2; inv h1; inv h2.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
have e: Arr U U1 = Arr U0 U2 by apply ih1 with (Γ:=Γ) (a:=a) (b:=b).
by inv e.
- move=> s1 t1 s2 t2 _ ih1 _ ih2 Γ U1 U2 a b h1 h2.
inv h1.
inv h2.
by apply ih1 with (Γ:=Γ) (a:=a) (b:=b).
Qed.
Lemma box_rel2_box_ids P s t :
box_rel2 P (Box s) (Box t) ->
exists U, closed s /\ [ ⊢ s :- U ] /\
closed t /\ [ ⊢ t :- U ] /\
strongly2 (logrel2 P U) s t.
Proof.
move=> h; inv h.
exists U; do 4 (split=>//).
have hh: strongly2 (logrel2 P U) s.|[ids] t.|[ids] by apply H5.
by asimpl in hh.
Qed.
Lemma box_rel2_nobox P s :
~ mem_box s -> box_rel2 P s s.
Proof.
elim: s
=> [x|||s hs t ht|s hs t ht|s hs S|s hs W|s hs f|s hs|s hs|s hs|s hs] /= h;
try by constructor.
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- constructor; by [apply hs=> ?; apply h; left | apply ht=> ?; apply h; right].
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by constructor; apply hs.
- by exfalso; apply h.
Qed.