Tealeaves.Backends.Multisorted.LN.LN
From Tealeaves.Backends.Common Require Import
Names AtomSet.
From Tealeaves.Misc Require Import
NaturalNumbers.
From Tealeaves.Theory Require Import
DecoratedTraversableMonad (* Mostly for the imports *)
Multisorted.DecoratedTraversableMonad.
Import
Product.Notations
Monoid.Notations
List.ListNotations
Subset.Notations
Kleisli.Monad.Notations
Kleisli.Comonad.Notations
ContainerFunctor.Notations
DecoratedMonad.Notations
DecoratedContainerFunctor.Notations
DecoratedTraversableMonad.Notations
AtomSet.Notations
DecoratedTraversableMonad.Notations
Functors.Multisorted.Batch.Notations
Theory.Container.Notations
Categories.TypeFamily.Notations.
#[local] Open Scope nat_scope. (* Let <<x + y>> be addition, not sum type. *)
#[local] Open Scope set_scope. (* Don't confuse with Functors/Subset.v *)
#[local] Generalizable Variable T.
Names AtomSet.
From Tealeaves.Misc Require Import
NaturalNumbers.
From Tealeaves.Theory Require Import
DecoratedTraversableMonad (* Mostly for the imports *)
Multisorted.DecoratedTraversableMonad.
Import
Product.Notations
Monoid.Notations
List.ListNotations
Subset.Notations
Kleisli.Monad.Notations
Kleisli.Comonad.Notations
ContainerFunctor.Notations
DecoratedMonad.Notations
DecoratedContainerFunctor.Notations
DecoratedTraversableMonad.Notations
AtomSet.Notations
DecoratedTraversableMonad.Notations
Functors.Multisorted.Batch.Notations
Theory.Container.Notations
Categories.TypeFamily.Notations.
#[local] Open Scope nat_scope. (* Let <<x + y>> be addition, not sum type. *)
#[local] Open Scope set_scope. (* Don't confuse with Functors/Subset.v *)
#[local] Generalizable Variable T.
Binders contexts
We assume that binder contexts are lists of tagged values of typeunit
, which are just tags themselves.
Section operations_on_context.
Context
`{Index}.
Fixpoint countk (j : K) (l : list K) : nat :=
match l with
| nil ⇒ 0
| cons k rest ⇒
(if j == k then 1 else 0) + countk j rest
end.
Lemma countk_nil : ∀ j, countk j nil = 0.
Proof.
easy.
Qed.
Lemma countk_one_eq : ∀ j, countk j [j] = 1.
Proof.
intros. cbn. compare values j and j.
Qed.
Lemma countk_one_neq : ∀ j k, j ≠ k → countk j [k] = 0.
Proof.
intros. cbn. compare values j and k.
Qed.
Lemma countk_cons_eq : ∀ j l, countk j (j :: l) = S (countk j l).
Proof.
intros. cbn. compare values j and j.
Qed.
Lemma countk_cons_neq : ∀ j k l, j ≠ k → countk j (k :: l) = countk j l.
Proof.
intros. cbn. compare values j and k.
Qed.
Lemma countk_app : ∀ j l1 l2, countk j (l1 ++ l2) = countk j l1 + countk j l2.
Proof.
intros. induction l1.
- easy.
- cbn. compare values j and a.
now rewrite IHl1.
Qed.
End operations_on_context.
Context
`{Index}.
Fixpoint countk (j : K) (l : list K) : nat :=
match l with
| nil ⇒ 0
| cons k rest ⇒
(if j == k then 1 else 0) + countk j rest
end.
Lemma countk_nil : ∀ j, countk j nil = 0.
Proof.
easy.
Qed.
Lemma countk_one_eq : ∀ j, countk j [j] = 1.
Proof.
intros. cbn. compare values j and j.
Qed.
Lemma countk_one_neq : ∀ j k, j ≠ k → countk j [k] = 0.
Proof.
intros. cbn. compare values j and k.
Qed.
Lemma countk_cons_eq : ∀ j l, countk j (j :: l) = S (countk j l).
Proof.
intros. cbn. compare values j and j.
Qed.
Lemma countk_cons_neq : ∀ j k l, j ≠ k → countk j (k :: l) = countk j l.
Proof.
intros. cbn. compare values j and k.
Qed.
Lemma countk_app : ∀ j l1 l2, countk j (l1 ++ l2) = countk j l1 + countk j l2.
Proof.
intros. induction l1.
- easy.
- cbn. compare values j and a.
now rewrite IHl1.
Qed.
End operations_on_context.
Inductive LN :=
| Fr : atom → LN
| Bd : nat → LN.
Theorem eq_dec_LN : ∀ l1 l2 : LN, {l1 = l2} + {l1 ≠ l2}.
Proof.
decide equality.
- compare values n and n0; auto.
- compare values n and n0; auto.
Qed.
#[export] Instance EqDec_LN : EquivDec.EqDec LN eq := eq_dec_LN.
Lemma compare_to_atom : ∀ x l (P : LN → Prop),
P (Fr x) →
(∀ a : atom, a ≠ x → P (Fr a)) →
(∀ n : nat, P (Bd n)) →
P l.
Proof.
introv case1 case2 case3. destruct l.
- destruct_eq_args x n. auto.
- auto.
Qed.
Tactic Notation "compare" constr(l) "to" "atom" constr(x) :=
(induction l using (compare_to_atom x)).
| Fr : atom → LN
| Bd : nat → LN.
Theorem eq_dec_LN : ∀ l1 l2 : LN, {l1 = l2} + {l1 ≠ l2}.
Proof.
decide equality.
- compare values n and n0; auto.
- compare values n and n0; auto.
Qed.
#[export] Instance EqDec_LN : EquivDec.EqDec LN eq := eq_dec_LN.
Lemma compare_to_atom : ∀ x l (P : LN → Prop),
P (Fr x) →
(∀ a : atom, a ≠ x → P (Fr a)) →
(∀ n : nat, P (Bd n)) →
P l.
Proof.
introv case1 case2 case3. destruct l.
- destruct_eq_args x n. auto.
- auto.
Qed.
Tactic Notation "compare" constr(l) "to" "atom" constr(x) :=
(induction l using (compare_to_atom x)).
Section local_operations.
Context
`{Index}
`{MReturn T}.
Implicit Types (x : atom) (k : K).
Definition free_loc : LN → list atom :=
fun l ⇒ match l with
| Fr x ⇒ cons x List.nil
| _ ⇒ List.nil
end.
Definition subst_loc k x (u : T k LN) : LN → T k LN :=
fun l ⇒ match l with
| Fr y ⇒
if x == y then u else mret T k (Fr y)
| Bd n ⇒
mret T k (Bd n)
end.
Definition open_loc k (u : T k LN) : list K × LN → T k LN :=
fun '(w, l) ⇒
match l with
| Fr x ⇒ mret T k (Fr x)
| Bd n ⇒
match Nat.compare n (countk k w) with
| Gt ⇒ mret T k (Bd (n - 1))
| Eq ⇒ u
| Lt ⇒ mret T k (Bd n)
end
end.
Definition is_opened : list K × (K × LN) → Prop :=
fun '(w, (k, l)) ⇒
match l with
| Fr y ⇒ False
| Bd n ⇒ n = countk k w
end.
Definition close_loc k x : list K × LN → LN :=
fun '(w, l) ⇒
match l with
| Fr y ⇒
if x == y then Bd (countk k w) else Fr y
| Bd n ⇒
match Nat.compare n (countk k w) with
| Gt ⇒ Bd (S n)
| Eq ⇒ Bd (S n)
| Lt ⇒ Bd n
end
end.
Context
`{Index}
`{MReturn T}.
Implicit Types (x : atom) (k : K).
Definition free_loc : LN → list atom :=
fun l ⇒ match l with
| Fr x ⇒ cons x List.nil
| _ ⇒ List.nil
end.
Definition subst_loc k x (u : T k LN) : LN → T k LN :=
fun l ⇒ match l with
| Fr y ⇒
if x == y then u else mret T k (Fr y)
| Bd n ⇒
mret T k (Bd n)
end.
Definition open_loc k (u : T k LN) : list K × LN → T k LN :=
fun '(w, l) ⇒
match l with
| Fr x ⇒ mret T k (Fr x)
| Bd n ⇒
match Nat.compare n (countk k w) with
| Gt ⇒ mret T k (Bd (n - 1))
| Eq ⇒ u
| Lt ⇒ mret T k (Bd n)
end
end.
Definition is_opened : list K × (K × LN) → Prop :=
fun '(w, (k, l)) ⇒
match l with
| Fr y ⇒ False
| Bd n ⇒ n = countk k w
end.
Definition close_loc k x : list K × LN → LN :=
fun '(w, l) ⇒
match l with
| Fr y ⇒
if x == y then Bd (countk k w) else Fr y
| Bd n ⇒
match Nat.compare n (countk k w) with
| Gt ⇒ Bd (S n)
| Eq ⇒ Bd (S n)
| Lt ⇒ Bd n
end
end.
To define local closure we will take
n = 0
, but we can also
consider more notions like ``local closure within a gap of 1
binder,'' which is useful for backend reasoning.
Definition lc_loc k (gap : nat) : list K × LN → Prop :=
fun '(w, l) ⇒
match l with
| Fr x ⇒ True
| Bd n ⇒ n < (countk k w) + gap
end.
End local_operations.
fun '(w, l) ⇒
match l with
| Fr x ⇒ True
| Bd n ⇒ n < (countk k w) + gap
end.
End local_operations.
Section LocallyNamelessOperations.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U
(mn_op := Monoid_op_list)
(mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Definition open k (u : T k LN) : U LN → U LN :=
kbindd U k (open_loc k u).
Definition close k x : U LN → U LN :=
kmapd U k (close_loc k x).
Definition subst k x (u : T k LN) : U LN → U LN :=
kbind U k (subst_loc k x u).
Definition free : K → U LN → list atom :=
fun k t ⇒ bind (T := list) free_loc (toklist U k t).
Definition LCn k (gap : nat) : U LN → Prop :=
fun t ⇒ ∀ (w : list K) (l : LN),
(w, (k, l)) ∈md t → lc_loc k gap (w, l).
Definition LC k : U LN → Prop :=
LCn k 0.
Definition FV : K → U LN → AtomSet.t :=
fun k t ⇒ AtomSet.atoms (free k t).
Definition scoped : K → U LN → AtomSet.t → Prop :=
fun k t γ ⇒ FV k t ⊆ γ.
End LocallyNamelessOperations.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U
(mn_op := Monoid_op_list)
(mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Definition open k (u : T k LN) : U LN → U LN :=
kbindd U k (open_loc k u).
Definition close k x : U LN → U LN :=
kmapd U k (close_loc k x).
Definition subst k x (u : T k LN) : U LN → U LN :=
kbind U k (subst_loc k x u).
Definition free : K → U LN → list atom :=
fun k t ⇒ bind (T := list) free_loc (toklist U k t).
Definition LCn k (gap : nat) : U LN → Prop :=
fun t ⇒ ∀ (w : list K) (l : LN),
(w, (k, l)) ∈md t → lc_loc k gap (w, l).
Definition LC k : U LN → Prop :=
LCn k 0.
Definition FV : K → U LN → AtomSet.t :=
fun k t ⇒ AtomSet.atoms (free k t).
Definition scoped : K → U LN → AtomSet.t → Prop :=
fun k t γ ⇒ FV k t ⊆ γ.
End LocallyNamelessOperations.
Module Notations.
Notation "t '{ k | x ~> u }" := (subst _ k x u t) (at level 35).
Notation "t '( k | u )" := (open _ k u t) (at level 35).
Notation "'[ k | x ] t" := (close _ k x t) (at level 35).
Notation "( x , y , z )" := (pair x (pair y z)) : tealeaves_multi_scope.
End Notations.
Section test_notations.
Import Notations.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Context
(k j : K)
(t1 : T k LN)
(t2 : T j LN)
(u : U LN)
(x : atom)
(n : nat).
Check u '{ k | x ~> t1}.
Check u '(k | t1).
Check '[k | x] u.
Check u '{j | x ~> t2}.
Check u '(j | t2).
Check '[j | x] u.
Fail Check u '{j | x ~> t1}.
Fail Check u '(j | t1).
End test_notations.
Import Notations.
(*|
##############################
Multisorted locally nameless infrastructure
##############################
|*)
(*|
---------------------------------------
Basic properties of operations
---------------------------------------
|*)
Section operations_specifications.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types (l : LN) (w : list K) (t : U LN) (x : atom).
Notation "t '{ k | x ~> u }" := (subst _ k x u t) (at level 35).
Notation "t '( k | u )" := (open _ k u t) (at level 35).
Notation "'[ k | x ] t" := (close _ k x t) (at level 35).
Notation "( x , y , z )" := (pair x (pair y z)) : tealeaves_multi_scope.
End Notations.
Section test_notations.
Import Notations.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Context
(k j : K)
(t1 : T k LN)
(t2 : T j LN)
(u : U LN)
(x : atom)
(n : nat).
Check u '{ k | x ~> t1}.
Check u '(k | t1).
Check '[k | x] u.
Check u '{j | x ~> t2}.
Check u '(j | t2).
Check '[j | x] u.
Fail Check u '{j | x ~> t1}.
Fail Check u '(j | t1).
End test_notations.
Import Notations.
(*|
##############################
Multisorted locally nameless infrastructure
##############################
|*)
(*|
---------------------------------------
Basic properties of operations
---------------------------------------
|*)
Section operations_specifications.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types (l : LN) (w : list K) (t : U LN) (x : atom).
Lemma open_eq : ∀ k t (u1 u2 : T k LN),
(∀ (w : list K) (l : LN), (w, (k, l)) ∈md t → open_loc k u1 (w, l) = open_loc k u2 (w, l)) →
t '(k | u1) = t '(k | u2).
Proof.
introv hyp. unfold open. apply kbindd_respectful. auto.
Qed.
Lemma open_id : ∀ k t u,
(∀ w l, (w, (k, l)) ∈md t → open_loc k u (w, l) = mret T k l) →
t '(k | u) = t.
Proof.
intros. unfold open.
now apply (kbindd_respectful_id k).
Qed.
(∀ (w : list K) (l : LN), (w, (k, l)) ∈md t → open_loc k u1 (w, l) = open_loc k u2 (w, l)) →
t '(k | u1) = t '(k | u2).
Proof.
introv hyp. unfold open. apply kbindd_respectful. auto.
Qed.
Lemma open_id : ∀ k t u,
(∀ w l, (w, (k, l)) ∈md t → open_loc k u (w, l) = mret T k l) →
t '(k | u) = t.
Proof.
intros. unfold open.
now apply (kbindd_respectful_id k).
Qed.
Lemma subst_eq : ∀ k t x u1 u2,
(∀ l, (k, l) ∈m t → subst_loc k x u1 l = subst_loc k x u2 l) →
t '{k | x ~> u1} = t '{k | x ~> u2}.
Proof.
introv hyp. unfold subst. apply kbind_respectful. auto.
Qed.
Lemma subst_id : ∀ k t x u,
(∀ l, (k, l) ∈m t → subst_loc k x u l = mret T k l) →
t '{k | x ~> u} = t.
Proof.
intros. unfold subst.
now apply kbind_respectful_id.
Qed.
(∀ l, (k, l) ∈m t → subst_loc k x u1 l = subst_loc k x u2 l) →
t '{k | x ~> u1} = t '{k | x ~> u2}.
Proof.
introv hyp. unfold subst. apply kbind_respectful. auto.
Qed.
Lemma subst_id : ∀ k t x u,
(∀ l, (k, l) ∈m t → subst_loc k x u l = mret T k l) →
t '{k | x ~> u} = t.
Proof.
intros. unfold subst.
now apply kbind_respectful_id.
Qed.
For close
Lemma close_eq : ∀ k t x y,
(∀ w l, (w, (k, l)) ∈md t → close_loc k x (w, l) = close_loc k y (w, l)) →
'[k | x] t = '[k | y] t.
Proof.
intros. unfold close.
now apply (kmapd_respectful).
Qed.
Lemma close_id : ∀ k t x,
(∀ w l, (w, (k, l)) ∈md t → close_loc k x (w, l) = l) →
'[k | x] t = t.
Proof.
intros. unfold close.
now apply (kmapd_respectful_id).
Qed.
(∀ w l, (w, (k, l)) ∈md t → close_loc k x (w, l) = close_loc k y (w, l)) →
'[k | x] t = '[k | y] t.
Proof.
intros. unfold close.
now apply (kmapd_respectful).
Qed.
Lemma close_id : ∀ k t x,
(∀ w l, (w, (k, l)) ∈md t → close_loc k x (w, l) = l) →
'[k | x] t = t.
Proof.
intros. unfold close.
now apply (kmapd_respectful_id).
Qed.
Lemma inmd_open_iff_eq : ∀ k l w u t,
(w, (k, l)) ∈md t '(k | u) ↔ ∃ w1 w2 l1,
(w1, (k, l1)) ∈md t ∧ (w2, (k, l)) ∈md open_loc k u (w1, l1) ∧ w = w1 ● w2.
Proof.
intros. unfold open.
now rewrite (inmd_kbindd_eq_iff U).
Qed.
Lemma inmd_open_neq_iff : ∀ k j l w u t,
k ≠ j →
(w, (k, l)) ∈md t '(j | u) ↔ (w, (k, l)) ∈md t ∨ ∃ w1 w2 l1,
(w1, (j, l1)) ∈md t ∧ (w2, (k, l)) ∈md open_loc j u (w1, l1) ∧ w = w1 ● w2.
Proof.
intros. unfold open.
now rewrite (inmd_kbindd_neq_iff U); auto.
Qed.
(w, (k, l)) ∈md t '(k | u) ↔ ∃ w1 w2 l1,
(w1, (k, l1)) ∈md t ∧ (w2, (k, l)) ∈md open_loc k u (w1, l1) ∧ w = w1 ● w2.
Proof.
intros. unfold open.
now rewrite (inmd_kbindd_eq_iff U).
Qed.
Lemma inmd_open_neq_iff : ∀ k j l w u t,
k ≠ j →
(w, (k, l)) ∈md t '(j | u) ↔ (w, (k, l)) ∈md t ∨ ∃ w1 w2 l1,
(w1, (j, l1)) ∈md t ∧ (w2, (k, l)) ∈md open_loc j u (w1, l1) ∧ w = w1 ● w2.
Proof.
intros. unfold open.
now rewrite (inmd_kbindd_neq_iff U); auto.
Qed.
For close
Lemma inmd_close_iff_eq : ∀ k l w x t,
(w, (k, l)) ∈md '[k | x] t ↔ ∃ l1,
(w, (k, l1)) ∈md t ∧ l = close_loc k x (w, l1).
Proof.
intros. unfold close.
rewrite (inmd_kmapd_eq_iff U).
easy.
Qed.
Lemma inmd_close_neq_iff : ∀ k j l w x t,
j ≠ k →
(w, (k, l)) ∈md '[j | x] t ↔ (w, (k, l)) ∈md t.
Proof.
intros. unfold close.
now rewrite (inmd_kmapd_neq_iff U).
Qed.
(w, (k, l)) ∈md '[k | x] t ↔ ∃ l1,
(w, (k, l1)) ∈md t ∧ l = close_loc k x (w, l1).
Proof.
intros. unfold close.
rewrite (inmd_kmapd_eq_iff U).
easy.
Qed.
Lemma inmd_close_neq_iff : ∀ k j l w x t,
j ≠ k →
(w, (k, l)) ∈md '[j | x] t ↔ (w, (k, l)) ∈md t.
Proof.
intros. unfold close.
now rewrite (inmd_kmapd_neq_iff U).
Qed.
Lemma inmd_subst_iff_eq : ∀ k w l u t x,
(w, (k, l)) ∈md t '{k | x ~> u} ↔ ∃ w1 w2 l1,
(w1, (k, l1)) ∈md t ∧ (w2, (k, l)) ∈md subst_loc k x u l1 ∧ w = w1 ● w2.
Proof.
intros. unfold subst.
now rewrite (inmd_kbind_eq_iff U).
Qed.
Lemma inmd_subst_neq_iff : ∀ k j w l u t x,
k ≠ j →
(w, (k, l)) ∈md t '{j | x ~> u} ↔ (w, (k, l)) ∈md t ∨ ∃ w1 w2 l1,
(w1, (j, l1)) ∈md t ∧ (w2, (k, l)) ∈md subst_loc j x u l1 ∧ w = w1 ● w2.
Proof.
intros. unfold subst.
now rewrite (inmd_kbind_neq_iff U); auto.
Qed.
(w, (k, l)) ∈md t '{k | x ~> u} ↔ ∃ w1 w2 l1,
(w1, (k, l1)) ∈md t ∧ (w2, (k, l)) ∈md subst_loc k x u l1 ∧ w = w1 ● w2.
Proof.
intros. unfold subst.
now rewrite (inmd_kbind_eq_iff U).
Qed.
Lemma inmd_subst_neq_iff : ∀ k j w l u t x,
k ≠ j →
(w, (k, l)) ∈md t '{j | x ~> u} ↔ (w, (k, l)) ∈md t ∨ ∃ w1 w2 l1,
(w1, (j, l1)) ∈md t ∧ (w2, (k, l)) ∈md subst_loc j x u l1 ∧ w = w1 ● w2.
Proof.
intros. unfold subst.
now rewrite (inmd_kbind_neq_iff U); auto.
Qed.
Lemma in_open_eq_iff : ∀ k l u t,
(k, l) ∈m t '(k | u) ↔ ∃ w1 l1,
(w1, (k, l1)) ∈md t ∧ (k, l) ∈m open_loc k u (w1, l1).
Proof.
intros. unfold open.
now rewrite (in_kbindd_eq_iff U).
Qed.
Lemma in_open_neq_iff : ∀ k j l u t,
k ≠ j →
(k, l) ∈m t '(j | u) ↔ (k, l) ∈m t ∨ ∃ w1 l1,
(w1, (j, l1)) ∈md t ∧ (k, l) ∈m open_loc j u (w1, l1).
Proof.
intros. unfold open.
now rewrite (in_kbindd_neq_iff U); auto.
Qed.
(k, l) ∈m t '(k | u) ↔ ∃ w1 l1,
(w1, (k, l1)) ∈md t ∧ (k, l) ∈m open_loc k u (w1, l1).
Proof.
intros. unfold open.
now rewrite (in_kbindd_eq_iff U).
Qed.
Lemma in_open_neq_iff : ∀ k j l u t,
k ≠ j →
(k, l) ∈m t '(j | u) ↔ (k, l) ∈m t ∨ ∃ w1 l1,
(w1, (j, l1)) ∈md t ∧ (k, l) ∈m open_loc j u (w1, l1).
Proof.
intros. unfold open.
now rewrite (in_kbindd_neq_iff U); auto.
Qed.
For close
Lemma in_close_eq_iff : ∀ k l x t,
(k, l) ∈m '[k | x] t ↔ ∃ w l1,
(w, (k, l1)) ∈md t ∧ l = close_loc k x (w, l1).
Proof.
intros. unfold close.
now rewrite (in_kmapd_eq_iff U).
Qed.
Lemma in_close_neq_iff : ∀ k j l x t,
k ≠ j →
(k, l) ∈m '[j | x] t ↔ (k, l) ∈m t.
Proof.
intros. unfold close.
now rewrite (in_kmapd_neq_iff U); auto.
Qed.
(k, l) ∈m '[k | x] t ↔ ∃ w l1,
(w, (k, l1)) ∈md t ∧ l = close_loc k x (w, l1).
Proof.
intros. unfold close.
now rewrite (in_kmapd_eq_iff U).
Qed.
Lemma in_close_neq_iff : ∀ k j l x t,
k ≠ j →
(k, l) ∈m '[j | x] t ↔ (k, l) ∈m t.
Proof.
intros. unfold close.
now rewrite (in_kmapd_neq_iff U); auto.
Qed.
Lemma in_subst_eq_iff : ∀ k l u t x,
(k, l) ∈m t '{k | x ~> u} ↔ ∃ l1,
(k, l1) ∈m t ∧ (k, l) ∈m subst_loc k x u l1.
Proof.
intros. unfold subst.
now rewrite (in_kbind_eq_iff U).
Qed.
Lemma in_subst_neq_iff : ∀ k j l u t x,
j ≠ k →
(k, l) ∈m t '{j | x ~> u} ↔ (k, l) ∈m t ∨ ∃ l1,
(j, l1) ∈m t ∧ (k, l) ∈m subst_loc j x u l1.
Proof.
intros. unfold subst.
now rewrite (in_kbind_neq_iff U).
Qed.
End operations_specifications.
(k, l) ∈m t '{k | x ~> u} ↔ ∃ l1,
(k, l1) ∈m t ∧ (k, l) ∈m subst_loc k x u l1.
Proof.
intros. unfold subst.
now rewrite (in_kbind_eq_iff U).
Qed.
Lemma in_subst_neq_iff : ∀ k j l u t x,
j ≠ k →
(k, l) ∈m t '{j | x ~> u} ↔ (k, l) ∈m t ∨ ∃ l1,
(j, l1) ∈m t ∧ (k, l) ∈m subst_loc j x u l1.
Proof.
intros. unfold subst.
now rewrite (in_kbind_neq_iff U).
Qed.
End operations_specifications.
Section characterize_free.
Context
{U : Type → Type}
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
#[local] Instance: Compat_ToSubset_Tolist list.
Proof.
unfold Compat_ToSubset_Tolist.
unfold tosubset, ToSubset_list.
unfold ToSubset_Tolist, ToSubset_list.
unfold compose. ext A l.
rewrite Tolist_list_id.
unfold tosubset.
reflexivity.
Qed.
Theorem in_free_iff : ∀ (k : K) (t : U LN) (x : atom),
x ∈ free U k t ↔ (k, Fr x) ∈m t.
Proof.
intros. unfold free.
replace (x ∈ bind free_loc (toklist U k t)) with
(x ∈ tolist (bind free_loc (toklist U k t))) by
now (rewrite Tolist_list_id).
rewrite <- in_iff_in_tolist.
rewrite in_bind_iff.
split.
- intros [l [lin xin]].
rewrite in_iff_in_toklist.
destruct l as [a|n].
+ cbv in xin. destruct xin as [?|[]].
subst. cbn in lin. assumption.
+ cbv in xin. destruct xin as [].
- intros. ∃ (Fr x). rewrite <- (in_iff_in_toklist).
split; [assumption| ].
cbv. now left.
Qed.
Corollary free_iff_FV : ∀ (k : K) (t : U LN) (x : atom),
x ∈ free U k t ↔ x `in` FV U k t.
Proof.
intros. unfold FV. rewrite <- in_atoms_iff.
reflexivity.
Qed.
End characterize_free.
Context
{U : Type → Type}
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
#[local] Instance: Compat_ToSubset_Tolist list.
Proof.
unfold Compat_ToSubset_Tolist.
unfold tosubset, ToSubset_list.
unfold ToSubset_Tolist, ToSubset_list.
unfold compose. ext A l.
rewrite Tolist_list_id.
unfold tosubset.
reflexivity.
Qed.
Theorem in_free_iff : ∀ (k : K) (t : U LN) (x : atom),
x ∈ free U k t ↔ (k, Fr x) ∈m t.
Proof.
intros. unfold free.
replace (x ∈ bind free_loc (toklist U k t)) with
(x ∈ tolist (bind free_loc (toklist U k t))) by
now (rewrite Tolist_list_id).
rewrite <- in_iff_in_tolist.
rewrite in_bind_iff.
split.
- intros [l [lin xin]].
rewrite in_iff_in_toklist.
destruct l as [a|n].
+ cbv in xin. destruct xin as [?|[]].
subst. cbn in lin. assumption.
+ cbv in xin. destruct xin as [].
- intros. ∃ (Fr x). rewrite <- (in_iff_in_toklist).
split; [assumption| ].
cbv. now left.
Qed.
Corollary free_iff_FV : ∀ (k : K) (t : U LN) (x : atom),
x ∈ free U k t ↔ x `in` FV U k t.
Proof.
intros. unfold FV. rewrite <- in_atoms_iff.
reflexivity.
Qed.
End characterize_free.
free variables after open
/close
/subst
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
After open
Lemma free_open_eq_iff : ∀ k u t x,
x ∈ free U k (t '(k | u)) ↔ ∃ w l1,
(w, (k, l1)) ∈md t ∧ x ∈ free (T k) k (open_loc k u (w, l1)).
Proof.
intros.
rewrite in_free_iff.
setoid_rewrite in_free_iff.
now rewrite in_open_eq_iff.
Qed.
Lemma free_open_neq_iff : ∀ k j u t x,
k ≠ j →
x ∈ free U j (t '(k | u)) ↔ x ∈ free U j t ∨ ∃ w l1,
(w, (k, l1)) ∈md t ∧ x ∈ free (T k) j (open_loc k u (w, l1)).
Proof.
intros. rewrite 2(in_free_iff). setoid_rewrite in_free_iff.
now rewrite in_open_neq_iff; auto.
Qed.
x ∈ free U k (t '(k | u)) ↔ ∃ w l1,
(w, (k, l1)) ∈md t ∧ x ∈ free (T k) k (open_loc k u (w, l1)).
Proof.
intros.
rewrite in_free_iff.
setoid_rewrite in_free_iff.
now rewrite in_open_eq_iff.
Qed.
Lemma free_open_neq_iff : ∀ k j u t x,
k ≠ j →
x ∈ free U j (t '(k | u)) ↔ x ∈ free U j t ∨ ∃ w l1,
(w, (k, l1)) ∈md t ∧ x ∈ free (T k) j (open_loc k u (w, l1)).
Proof.
intros. rewrite 2(in_free_iff). setoid_rewrite in_free_iff.
now rewrite in_open_neq_iff; auto.
Qed.
After close
Lemma free_close_eq_iff : ∀ k t x y,
y ∈ free U k ('[k | x] t) ↔ ∃ w l1,
(w, (k, l1)) ∈md t ∧ Fr y = close_loc k x (w, l1).
Proof.
intros. rewrite in_free_iff.
now rewrite (in_close_eq_iff U).
Qed.
Lemma free_close_neq_iff : ∀ k j t x,
k ≠ j →
x ∈ free U j ('[k | x] t) ↔ x ∈ free U j t.
Proof.
intros. rewrite 2(in_free_iff).
now rewrite (in_close_neq_iff U); auto.
Qed.
y ∈ free U k ('[k | x] t) ↔ ∃ w l1,
(w, (k, l1)) ∈md t ∧ Fr y = close_loc k x (w, l1).
Proof.
intros. rewrite in_free_iff.
now rewrite (in_close_eq_iff U).
Qed.
Lemma free_close_neq_iff : ∀ k j t x,
k ≠ j →
x ∈ free U j ('[k | x] t) ↔ x ∈ free U j t.
Proof.
intros. rewrite 2(in_free_iff).
now rewrite (in_close_neq_iff U); auto.
Qed.
Lemma free_subst_eq_iff : ∀ k u t x y,
y ∈ free U k (t '{k | x ~> u}) ↔ ∃ l1,
(k, l1) ∈m t ∧ y ∈ free (T k) k (subst_loc k x u l1).
Proof.
intros. rewrite (in_free_iff). setoid_rewrite (in_free_iff (U := T k)).
now rewrite (in_subst_eq_iff U).
Qed.
Lemma free_subst_neq_iff : ∀ j k u t x y,
k ≠ j →
y ∈ free U j (t '{k | x ~> u}) ↔ y ∈ free U j t ∨ ∃ l1,
(k, l1) ∈m t ∧ y ∈ free (T k) j (subst_loc k x u l1).
Proof.
intros. rewrite 2(in_free_iff). setoid_rewrite (in_free_iff (U := T k)).
now rewrite (in_subst_neq_iff); auto.
Qed.
End operations_specifications.
y ∈ free U k (t '{k | x ~> u}) ↔ ∃ l1,
(k, l1) ∈m t ∧ y ∈ free (T k) k (subst_loc k x u l1).
Proof.
intros. rewrite (in_free_iff). setoid_rewrite (in_free_iff (U := T k)).
now rewrite (in_subst_eq_iff U).
Qed.
Lemma free_subst_neq_iff : ∀ j k u t x y,
k ≠ j →
y ∈ free U j (t '{k | x ~> u}) ↔ y ∈ free U j t ∨ ∃ l1,
(k, l1) ∈m t ∧ y ∈ free (T k) j (subst_loc k x u l1).
Proof.
intros. rewrite 2(in_free_iff). setoid_rewrite (in_free_iff (U := T k)).
now rewrite (in_subst_neq_iff); auto.
Qed.
End operations_specifications.
Lemmas for local reasoning
The following lemmas govern the behavior of the*_loc
operations of
the locally nameless library. These are put into a hint database
tea_local
to use with autorewrite
. Since autorewrite
tries the
first unifying lemma (even if this generates absurd side conditions), we
use Hint Rewrite ... using ...
clauses and typically prefer
autorewrite*
, which only uses hints whose side conditions are
discharged by the associated tactic.
Create HintDb tea_local.
Section locally_nameless_local.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types (l : LN) (w : list K) (t : U LN) (x : atom) (j k : K) (n : nat).
Section locally_nameless_local.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types (l : LN) (w : list K) (t : U LN) (x : atom) (j k : K) (n : nat).
Lemma Fr_injective : ∀ (x y : atom),
(Fr x = Fr y) ↔ (x = y).
Proof.
intros. split; intro hyp.
now injection hyp. now subst.
Qed.
Lemma Fr_injective_not_iff : ∀ (x y : atom),
(Fr x ≠ Fr y) ↔ (x ≠ y).
Proof.
intros. split; intro hyp; contradict hyp.
now subst. now injection hyp.
Qed.
Lemma Fr_injective_not : ∀ (x y : atom),
x ≠ y → ¬ (Fr x = Fr y).
Proof.
intros. now rewrite Fr_injective.
Qed.
Lemma B_neq_Fr : ∀ n x,
(Bd n = Fr x) = False.
Proof.
introv. propext. discriminate. contradiction.
Qed.
Lemma prod_K_not_iff : ∀ (k : K) A (x y : A),
((k, x) ≠ (k, y)) ↔ (x ≠ y).
Proof.
intros. split; intro hyp; contradict hyp.
now subst. now injection hyp.
Qed.
Lemma ninf_in_neq : ∀ k x l (t : U LN),
¬ x ∈ free U k t →
(k, l) ∈m t → Fr x ≠ l.
Proof.
introv hyp1 hyp2.
rewrite in_free_iff in hyp1. destruct l.
- injection. intros; subst.
contradiction.
- discriminate.
Qed.
Lemma neq_symmetry : ∀ X (x y : X),
(x ≠ y) = (y ≠ x).
Proof.
intros. propext; intro hyp; contradict hyp; congruence.
Qed.
(Fr x = Fr y) ↔ (x = y).
Proof.
intros. split; intro hyp.
now injection hyp. now subst.
Qed.
Lemma Fr_injective_not_iff : ∀ (x y : atom),
(Fr x ≠ Fr y) ↔ (x ≠ y).
Proof.
intros. split; intro hyp; contradict hyp.
now subst. now injection hyp.
Qed.
Lemma Fr_injective_not : ∀ (x y : atom),
x ≠ y → ¬ (Fr x = Fr y).
Proof.
intros. now rewrite Fr_injective.
Qed.
Lemma B_neq_Fr : ∀ n x,
(Bd n = Fr x) = False.
Proof.
introv. propext. discriminate. contradiction.
Qed.
Lemma prod_K_not_iff : ∀ (k : K) A (x y : A),
((k, x) ≠ (k, y)) ↔ (x ≠ y).
Proof.
intros. split; intro hyp; contradict hyp.
now subst. now injection hyp.
Qed.
Lemma ninf_in_neq : ∀ k x l (t : U LN),
¬ x ∈ free U k t →
(k, l) ∈m t → Fr x ≠ l.
Proof.
introv hyp1 hyp2.
rewrite in_free_iff in hyp1. destruct l.
- injection. intros; subst.
contradiction.
- discriminate.
Qed.
Lemma neq_symmetry : ∀ X (x y : X),
(x ≠ y) = (y ≠ x).
Proof.
intros. propext; intro hyp; contradict hyp; congruence.
Qed.
Lemma subst_loc_eq : ∀ k u x,
subst_loc k x u (Fr x) = u.
Proof.
intros. cbn. now compare values x and x.
Qed.
Lemma subst_loc_neq : ∀ k u x y,
y ≠ x →
subst_loc k x u (Fr y) = mret T k (Fr y).
Proof.
intros. cbn. now compare values x and y.
Qed.
Lemma subst_loc_b : ∀ k u x n,
subst_loc k x u (Bd n) = mret T k (Bd n).
Proof.
reflexivity.
Qed.
Lemma subst_loc_fr_neq : ∀ k u l x,
Fr x ≠ l →
subst_loc k x u l = mret T k l.
Proof.
introv neq. unfold subst_loc.
destruct l as [a|?]; [compare values x and a | reflexivity].
Qed.
Lemma subst_in_mret_eq : ∀ k x l u,
(mret T k l) '{k | x ~> u} = subst_loc k x u l.
Proof.
intros. unfold subst.
now rewrite kbind_comp_mret_eq.
Qed.
Lemma subst_in_mret_neq : ∀ k j x l u,
j ≠ k →
(mret T k l) '{j | x ~> u} = mret T k l.
Proof.
intros. unfold subst.
now rewrite kbind_comp_mret_neq.
Qed.
subst_loc k x u (Fr x) = u.
Proof.
intros. cbn. now compare values x and x.
Qed.
Lemma subst_loc_neq : ∀ k u x y,
y ≠ x →
subst_loc k x u (Fr y) = mret T k (Fr y).
Proof.
intros. cbn. now compare values x and y.
Qed.
Lemma subst_loc_b : ∀ k u x n,
subst_loc k x u (Bd n) = mret T k (Bd n).
Proof.
reflexivity.
Qed.
Lemma subst_loc_fr_neq : ∀ k u l x,
Fr x ≠ l →
subst_loc k x u l = mret T k l.
Proof.
introv neq. unfold subst_loc.
destruct l as [a|?]; [compare values x and a | reflexivity].
Qed.
Lemma subst_in_mret_eq : ∀ k x l u,
(mret T k l) '{k | x ~> u} = subst_loc k x u l.
Proof.
intros. unfold subst.
now rewrite kbind_comp_mret_eq.
Qed.
Lemma subst_in_mret_neq : ∀ k j x l u,
j ≠ k →
(mret T k l) '{j | x ~> u} = mret T k l.
Proof.
intros. unfold subst.
now rewrite kbind_comp_mret_neq.
Qed.
Lemma open_loc_lt : ∀ k u w n,
n < countk k w →
open_loc k u (w, Bd n) = mret T k (Bd n).
Proof.
introv ineq. unfold open_loc. compare naturals n and (countk k w).
Qed.
Lemma open_loc_gt : ∀ k u n w,
n > countk k w →
open_loc k u (w, Bd n) = mret T k (Bd (n - 1)).
Proof.
introv ineq. unfold open_loc. compare naturals n and (countk k w).
Qed.
Lemma open_loc_eq : ∀ k w u,
open_loc k u (w, Bd (countk k w)) = u.
Proof.
introv. unfold open_loc. compare naturals (countk k w) and (countk k w).
Qed.
Lemma open_loc_atom : ∀ k u w x,
open_loc k u (w, Fr x) = mret T k (Fr x).
Proof.
reflexivity.
Qed.
End locally_nameless_local.
n < countk k w →
open_loc k u (w, Bd n) = mret T k (Bd n).
Proof.
introv ineq. unfold open_loc. compare naturals n and (countk k w).
Qed.
Lemma open_loc_gt : ∀ k u n w,
n > countk k w →
open_loc k u (w, Bd n) = mret T k (Bd (n - 1)).
Proof.
introv ineq. unfold open_loc. compare naturals n and (countk k w).
Qed.
Lemma open_loc_eq : ∀ k w u,
open_loc k u (w, Bd (countk k w)) = u.
Proof.
introv. unfold open_loc. compare naturals (countk k w) and (countk k w).
Qed.
Lemma open_loc_atom : ∀ k u w x,
open_loc k u (w, Fr x) = mret T k (Fr x).
Proof.
reflexivity.
Qed.
End locally_nameless_local.
Tactic Notation "unfold_monoid" :=
repeat unfold monoid_op, Monoid_op_list, Monoid_op_list,
monoid_unit, Monoid_unit_list, Monoid_unit_list in ×.
#[export] Hint Rewrite @prod_K_not_iff : tea_local.
repeat unfold monoid_op, Monoid_op_list, Monoid_op_list,
monoid_unit, Monoid_unit_list, Monoid_unit_list in ×.
#[export] Hint Rewrite @prod_K_not_iff : tea_local.
Rewrite rules for expressions of the form
x ∈ mret T y
#[export] Hint Rewrite
@in_mret_iff @in_mret_eq_iff
@inmd_mret_iff @inmd_mret_eq_iff using typeclasses eauto : tea_local.
@in_mret_iff @in_mret_eq_iff
@inmd_mret_iff @inmd_mret_eq_iff using typeclasses eauto : tea_local.
Rewrite rules for simplifying expressions involving equalities between leaves
Solve goals of the form
Fr x <> Fr y
by using x <> y
#[export] Hint Resolve
Fr_injective_not : tea_local.
#[export] Hint Rewrite
@subst_loc_eq @subst_in_mret_eq
using typeclasses eauto : tea_local.
#[export] Hint Rewrite
@subst_loc_neq @subst_loc_b @subst_loc_fr_neq @subst_in_mret_neq
using first [ typeclasses eauto | auto ] : tea_local.
#[export] Hint Rewrite
@open_loc_lt @open_loc_gt
using first [ typeclasses eauto | auto ] : tea_local.
#[export] Hint Rewrite
@open_loc_eq @open_loc_atom
using typeclasses eauto : tea_local.
Tactic Notation "simpl_local" := (autorewrite× with tea_local).
Fr_injective_not : tea_local.
#[export] Hint Rewrite
@subst_loc_eq @subst_in_mret_eq
using typeclasses eauto : tea_local.
#[export] Hint Rewrite
@subst_loc_neq @subst_loc_b @subst_loc_fr_neq @subst_in_mret_neq
using first [ typeclasses eauto | auto ] : tea_local.
#[export] Hint Rewrite
@open_loc_lt @open_loc_gt
using first [ typeclasses eauto | auto ] : tea_local.
#[export] Hint Rewrite
@open_loc_eq @open_loc_atom
using typeclasses eauto : tea_local.
Tactic Notation "simpl_local" := (autorewrite× with tea_local).
Section subst_metatheory.
Section fix_dtm.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Section fix_dtm.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Lemma inmd_subst_loc_iff : ∀ k l w j p u x,
(w, (j, p)) ∈md subst_loc k x u l ↔
l ≠ Fr x ∧ k = j ∧ w = Ƶ ∧ l = p ∨ (* l is not replaced *)
l = Fr x ∧ (w, (j, p)) ∈md u. (* l is replaced *)
Proof.
introv. compare l to atom x.
- rewrite subst_loc_eq.
clear; firstorder.
- rewrite subst_loc_neq; auto.
rewrite inmd_mret_iff.
rewrite Fr_injective.
firstorder.
- rewrite subst_loc_b.
rewrite inmd_mret_iff.
rewrite B_neq_Fr.
firstorder.
Qed.
Corollary inmd_subst_loc_iff_eq : ∀ k l w p u x,
(w, (k, p)) ∈md subst_loc k x u l ↔
l ≠ Fr x ∧ w = Ƶ ∧ l = p ∨
l = Fr x ∧ (w, (k, p)) ∈md u.
Proof.
introv. rewrite inmd_subst_loc_iff. clear. firstorder.
Qed.
Corollary inmd_subst_loc_iff_neq : ∀ k l w j p u x,
k ≠ j →
(w, (j, p)) ∈md subst_loc k x u l ↔
l = Fr x ∧ (w, (j, p)) ∈md u.
Proof.
introv neq. rewrite inmd_subst_loc_iff. intuition.
Qed.
Theorem inmd_subst_iff : ∀ k j w t u l x,
(* <<l>> occurs in the result of a <<subst>> IFF *)
(w, j, l) ∈md t '{k | x ~> u} ↔
(* <<l>> is an occurrence in <<t>> not of the same sort as the <<subst>> OR *)
k ≠ j ∧ (w, j, l) ∈md t ∨
(* <<l>> is an occurrence of the same sort but not an occurrence of <<x>> OR *)
k = j ∧ (w, k, l) ∈md t ∧ l ≠ Fr x ∨
(* <<x>> occurs and <<l>> is the any LN in a substituted <<u>> *)
∃ w1 w2 : list K, (w1, k, Fr x) ∈md t ∧ (w2, j, l) ∈md u ∧ w = w1 ● w2.
Proof with auto.
intros. compare values k and j.
- rewrite (inmd_subst_iff_eq U). setoid_rewrite (inmd_subst_loc_iff_eq j).
split.
+ intros [l' [n1 [n2 conditions]]].
right. destruct conditions as [c1 [[c2|c2] c3]].
{ subst. left. destruct c2 as [c21 [c22 c23]]; subst.
rewrite monoid_id_r. auto. }
{ subst. right. destruct c2 as [c21 c22]; subst. eauto. }
+ intros [[contra ?] | [ [? [in_t neq]] | hyp ] ].
{ contradiction. }
{ ∃ w. ∃ (Ƶ : list K). ∃ l.
rewrite monoid_id_r. split... }
{ destruct hyp as [w1 [w2 ?]]. ∃ w1. ∃ w2. ∃ (Fr x). intuition. }
- rewrite (inmd_subst_neq_iff U)... split.
+ intros [? | [n1 [n2 [p [in_t in_local]]]]]...
rewrite (inmd_subst_loc_iff_neq k) in in_local...
right. right. ∃ n1. ∃ n2. destruct in_local as [[? ?] ?]; subst...
+ intros [[? ?] | [[? ?] | [w1 [w2 rest]]]].
{ auto. }
{ contradiction. }
{ right. ∃ w1. ∃ w2. ∃ (Fr x). simpl_local... }
Qed.
Corollary inmd_subst_iff_eq' : ∀ k w t u l x,
(w, k, l) ∈md t '{k | x ~> u} ↔
(w, k, l) ∈md t ∧ l ≠ Fr x ∨
∃ w1 w2 : list K, (w1, k, Fr x) ∈md t ∧ (w2, k, l) ∈md u ∧ w = w1 ● w2.
Proof.
intros. rewrite inmd_subst_iff. intuition.
Qed.
Corollary inmd_subst_iff_neq' : ∀ k j w t u l x,
k ≠ j →
(w, j, l) ∈md t '{k | x ~> u} ↔
(w, j, l) ∈md t ∨
∃ w1 w2 : list K, (w1, k, Fr x) ∈md t ∧ (w2, j, l) ∈md u ∧ w = w1 ● w2.
Proof.
intros. rewrite inmd_subst_iff. intuition.
Qed.
(w, (j, p)) ∈md subst_loc k x u l ↔
l ≠ Fr x ∧ k = j ∧ w = Ƶ ∧ l = p ∨ (* l is not replaced *)
l = Fr x ∧ (w, (j, p)) ∈md u. (* l is replaced *)
Proof.
introv. compare l to atom x.
- rewrite subst_loc_eq.
clear; firstorder.
- rewrite subst_loc_neq; auto.
rewrite inmd_mret_iff.
rewrite Fr_injective.
firstorder.
- rewrite subst_loc_b.
rewrite inmd_mret_iff.
rewrite B_neq_Fr.
firstorder.
Qed.
Corollary inmd_subst_loc_iff_eq : ∀ k l w p u x,
(w, (k, p)) ∈md subst_loc k x u l ↔
l ≠ Fr x ∧ w = Ƶ ∧ l = p ∨
l = Fr x ∧ (w, (k, p)) ∈md u.
Proof.
introv. rewrite inmd_subst_loc_iff. clear. firstorder.
Qed.
Corollary inmd_subst_loc_iff_neq : ∀ k l w j p u x,
k ≠ j →
(w, (j, p)) ∈md subst_loc k x u l ↔
l = Fr x ∧ (w, (j, p)) ∈md u.
Proof.
introv neq. rewrite inmd_subst_loc_iff. intuition.
Qed.
Theorem inmd_subst_iff : ∀ k j w t u l x,
(* <<l>> occurs in the result of a <<subst>> IFF *)
(w, j, l) ∈md t '{k | x ~> u} ↔
(* <<l>> is an occurrence in <<t>> not of the same sort as the <<subst>> OR *)
k ≠ j ∧ (w, j, l) ∈md t ∨
(* <<l>> is an occurrence of the same sort but not an occurrence of <<x>> OR *)
k = j ∧ (w, k, l) ∈md t ∧ l ≠ Fr x ∨
(* <<x>> occurs and <<l>> is the any LN in a substituted <<u>> *)
∃ w1 w2 : list K, (w1, k, Fr x) ∈md t ∧ (w2, j, l) ∈md u ∧ w = w1 ● w2.
Proof with auto.
intros. compare values k and j.
- rewrite (inmd_subst_iff_eq U). setoid_rewrite (inmd_subst_loc_iff_eq j).
split.
+ intros [l' [n1 [n2 conditions]]].
right. destruct conditions as [c1 [[c2|c2] c3]].
{ subst. left. destruct c2 as [c21 [c22 c23]]; subst.
rewrite monoid_id_r. auto. }
{ subst. right. destruct c2 as [c21 c22]; subst. eauto. }
+ intros [[contra ?] | [ [? [in_t neq]] | hyp ] ].
{ contradiction. }
{ ∃ w. ∃ (Ƶ : list K). ∃ l.
rewrite monoid_id_r. split... }
{ destruct hyp as [w1 [w2 ?]]. ∃ w1. ∃ w2. ∃ (Fr x). intuition. }
- rewrite (inmd_subst_neq_iff U)... split.
+ intros [? | [n1 [n2 [p [in_t in_local]]]]]...
rewrite (inmd_subst_loc_iff_neq k) in in_local...
right. right. ∃ n1. ∃ n2. destruct in_local as [[? ?] ?]; subst...
+ intros [[? ?] | [[? ?] | [w1 [w2 rest]]]].
{ auto. }
{ contradiction. }
{ right. ∃ w1. ∃ w2. ∃ (Fr x). simpl_local... }
Qed.
Corollary inmd_subst_iff_eq' : ∀ k w t u l x,
(w, k, l) ∈md t '{k | x ~> u} ↔
(w, k, l) ∈md t ∧ l ≠ Fr x ∨
∃ w1 w2 : list K, (w1, k, Fr x) ∈md t ∧ (w2, k, l) ∈md u ∧ w = w1 ● w2.
Proof.
intros. rewrite inmd_subst_iff. intuition.
Qed.
Corollary inmd_subst_iff_neq' : ∀ k j w t u l x,
k ≠ j →
(w, j, l) ∈md t '{k | x ~> u} ↔
(w, j, l) ∈md t ∨
∃ w1 w2 : list K, (w1, k, Fr x) ∈md t ∧ (w2, j, l) ∈md u ∧ w = w1 ● w2.
Proof.
intros. rewrite inmd_subst_iff. intuition.
Qed.
Lemma in_subst_loc_iff : ∀ k l j p u x,
(j, p) ∈m subst_loc k x u l ↔
l ≠ Fr x ∧ k = j ∧ l = p ∨
l = Fr x ∧ (j, p) ∈m u.
Proof.
introv. compare l to atom x; autorewrite× with tea_local; intuition.
Qed.
Corollary in_subst_loc_iff_eq : ∀ k l p u x,
(k, p) ∈m subst_loc k x u l ↔
l ≠ Fr x ∧ l = p ∨
l = Fr x ∧ (k, p) ∈m u.
Proof.
introv. rewrite in_subst_loc_iff; intuition.
Qed.
Corollary in_subst_loc_iff_neq : ∀ k l j p u x,
k ≠ j →
(j, p) ∈m subst_loc k x u l ↔
l = Fr x ∧ (j, p) ∈m u.
Proof.
introv neq. rewrite in_subst_loc_iff. intuition.
Qed.
Theorem in_subst_iff : ∀ k j t u l x,
(* <<l>> occurs in the result of a <<subst>> IFF *)
(j, l) ∈m t '{k | x ~> u} ↔
(* <<l>> is an occurrence in <<t>> not of the same sort as the <<subst>> OR *)
k ≠ j ∧ (j, l) ∈m t ∨
(* <<l>> is an occurrence of the same sort but not an occurrence of <<x>> OR *)
k = j ∧ (k, l) ∈m t ∧ l ≠ Fr x ∨
(* <<x>> occurs and <<l>> is the any LN in a substituted <<u>> *)
(k, Fr x) ∈m t ∧ (j, l) ∈m u.
Proof with auto.
intros. destruct_eq_args k j.
- rewrite (in_subst_eq_iff U).
setoid_rewrite (in_subst_loc_iff_eq). split.
+ intros [? [? in_sub]].
destruct in_sub as [[? heq] | [heq ?]]; subst...
+ intros [[contra ?] | [ [? [in_t neq]] | ? ] ].
{ contradiction. }
{ ∃ l... }
{ ∃ (Fr x). intuition. }
- rewrite (in_subst_neq_iff U); auto. split.
+ intros [? | [p [in_t in_local]] ]; auto.
rewrite in_subst_loc_iff_neq in in_local; auto.
destruct in_local as [? ?]; subst. auto.
+ intros [[? ?] | [[? ?] | ?]].
{ auto. }
{ contradiction. }
{ right. ∃ (Fr x). simpl_local... }
Qed.
Corollary in_subst_iff_eq : ∀ k t u l x,
(k, l) ∈m t '{k | x ~> u} ↔
(k, l) ∈m t ∧ l ≠ Fr x ∨
(k, Fr x) ∈m t ∧ (k, l) ∈m u.
Proof with auto.
intros. rewrite in_subst_iff. intuition.
Qed.
Corollary in_subst_iff_neq : ∀ k j t u l x,
k ≠ j →
(j, l) ∈m t '{k | x ~> u} ↔
(j, l) ∈m t ∨
(k, Fr x) ∈m t ∧ (j, l) ∈m u.
Proof with auto.
intros. rewrite in_subst_iff. intuition.
Qed.
(j, p) ∈m subst_loc k x u l ↔
l ≠ Fr x ∧ k = j ∧ l = p ∨
l = Fr x ∧ (j, p) ∈m u.
Proof.
introv. compare l to atom x; autorewrite× with tea_local; intuition.
Qed.
Corollary in_subst_loc_iff_eq : ∀ k l p u x,
(k, p) ∈m subst_loc k x u l ↔
l ≠ Fr x ∧ l = p ∨
l = Fr x ∧ (k, p) ∈m u.
Proof.
introv. rewrite in_subst_loc_iff; intuition.
Qed.
Corollary in_subst_loc_iff_neq : ∀ k l j p u x,
k ≠ j →
(j, p) ∈m subst_loc k x u l ↔
l = Fr x ∧ (j, p) ∈m u.
Proof.
introv neq. rewrite in_subst_loc_iff. intuition.
Qed.
Theorem in_subst_iff : ∀ k j t u l x,
(* <<l>> occurs in the result of a <<subst>> IFF *)
(j, l) ∈m t '{k | x ~> u} ↔
(* <<l>> is an occurrence in <<t>> not of the same sort as the <<subst>> OR *)
k ≠ j ∧ (j, l) ∈m t ∨
(* <<l>> is an occurrence of the same sort but not an occurrence of <<x>> OR *)
k = j ∧ (k, l) ∈m t ∧ l ≠ Fr x ∨
(* <<x>> occurs and <<l>> is the any LN in a substituted <<u>> *)
(k, Fr x) ∈m t ∧ (j, l) ∈m u.
Proof with auto.
intros. destruct_eq_args k j.
- rewrite (in_subst_eq_iff U).
setoid_rewrite (in_subst_loc_iff_eq). split.
+ intros [? [? in_sub]].
destruct in_sub as [[? heq] | [heq ?]]; subst...
+ intros [[contra ?] | [ [? [in_t neq]] | ? ] ].
{ contradiction. }
{ ∃ l... }
{ ∃ (Fr x). intuition. }
- rewrite (in_subst_neq_iff U); auto. split.
+ intros [? | [p [in_t in_local]] ]; auto.
rewrite in_subst_loc_iff_neq in in_local; auto.
destruct in_local as [? ?]; subst. auto.
+ intros [[? ?] | [[? ?] | ?]].
{ auto. }
{ contradiction. }
{ right. ∃ (Fr x). simpl_local... }
Qed.
Corollary in_subst_iff_eq : ∀ k t u l x,
(k, l) ∈m t '{k | x ~> u} ↔
(k, l) ∈m t ∧ l ≠ Fr x ∨
(k, Fr x) ∈m t ∧ (k, l) ∈m u.
Proof with auto.
intros. rewrite in_subst_iff. intuition.
Qed.
Corollary in_subst_iff_neq : ∀ k j t u l x,
k ≠ j →
(j, l) ∈m t '{k | x ~> u} ↔
(j, l) ∈m t ∨
(k, Fr x) ∈m t ∧ (j, l) ∈m u.
Proof with auto.
intros. rewrite in_subst_iff. intuition.
Qed.
Corollary in_free_subst_iff_eq : ∀ t k u x y,
y ∈ free U k (t '{k | x ~> u}) ↔
y ∈ free U k t ∧ y ≠ x ∨ x ∈ free U k t ∧ y ∈ free (T k) k u.
Proof.
intros. repeat rewrite (in_free_iff).
rewrite in_subst_iff_eq. now simpl_local.
Qed.
Corollary in_FV_subst_iff_eq : ∀ t k u x y,
y `in` FV U k (t '{k | x ~> u}) ↔
y `in` FV U k t ∧ y ≠ x ∨
x `in` FV U k t ∧ y `in` FV (T k) k u.
Proof.
intros. repeat rewrite <- (free_iff_FV).
apply in_free_subst_iff_eq.
Qed.
Corollary in_free_subst_iff_neq : ∀ t k j u x y,
k ≠ j →
y ∈ free U j (t '{k | x ~> u}) ↔
y ∈ free U j t ∨ x ∈ free U k t ∧ y ∈ free (T k) j u.
Proof.
intros. repeat rewrite (in_free_iff).
rewrite in_subst_iff_neq; auto. reflexivity.
Qed.
Corollary in_FV_subst_iff_neq : ∀ t k j u x y,
k ≠ j →
y `in` FV U j (t '{k | x ~> u}) ↔
y `in` FV U j t ∨
x `in` FV U k t ∧ y `in` FV (T k) j u.
Proof.
intros. repeat rewrite <- (free_iff_FV).
auto using in_free_subst_iff_neq.
Qed.
y ∈ free U k (t '{k | x ~> u}) ↔
y ∈ free U k t ∧ y ≠ x ∨ x ∈ free U k t ∧ y ∈ free (T k) k u.
Proof.
intros. repeat rewrite (in_free_iff).
rewrite in_subst_iff_eq. now simpl_local.
Qed.
Corollary in_FV_subst_iff_eq : ∀ t k u x y,
y `in` FV U k (t '{k | x ~> u}) ↔
y `in` FV U k t ∧ y ≠ x ∨
x `in` FV U k t ∧ y `in` FV (T k) k u.
Proof.
intros. repeat rewrite <- (free_iff_FV).
apply in_free_subst_iff_eq.
Qed.
Corollary in_free_subst_iff_neq : ∀ t k j u x y,
k ≠ j →
y ∈ free U j (t '{k | x ~> u}) ↔
y ∈ free U j t ∨ x ∈ free U k t ∧ y ∈ free (T k) j u.
Proof.
intros. repeat rewrite (in_free_iff).
rewrite in_subst_iff_neq; auto. reflexivity.
Qed.
Corollary in_FV_subst_iff_neq : ∀ t k j u x y,
k ≠ j →
y `in` FV U j (t '{k | x ~> u}) ↔
y `in` FV U j t ∨
x `in` FV U k t ∧ y `in` FV (T k) j u.
Proof.
intros. repeat rewrite <- (free_iff_FV).
auto using in_free_subst_iff_neq.
Qed.
Corollary in_subst_upper : ∀ k j t u l x,
(j, l) ∈m t '{k | x ~> u} →
(j, l) ∈m t ∧ (j, l) ≠ (k, Fr x) ∨ (j, l) ∈m u.
Proof with auto.
introv hin. rewrite in_subst_iff in hin.
destruct hin as [[hyp1 hyp2] | [hyp | hyp] ].
- left. split; [assumption |]. injection...
- destruct hyp as [hyp1 [hyp2 hyp3]]. subst. left.
split; [assumption |]. injection...
- intuition.
Qed.
Corollary in_subst_upper_eq : ∀ k t u l x,
(k, l) ∈m t '{k | x ~> u} →
(k, l) ∈m t ∧ l ≠ Fr x ∨ (k, l) ∈m u.
Proof.
introv hyp. apply in_subst_upper in hyp.
autorewrite× with tea_local in hyp.
intuition.
Qed.
Corollary in_subst_upper_neq : ∀ k j t u l x,
k ≠ j →
(j, l) ∈m t '{k | x ~> u} →
(j, l) ∈m t ∨ (j, l) ∈m u.
Proof.
introv neq hyp. apply in_subst_upper in hyp.
intuition.
Qed.
Corollary in_free_subst_upper : ∀ k j t u x y,
y ∈ free U j (t '{k | x ~> u}) →
(y ∈ free U j t ∧ j ≠ k) ∨ (y ∈ free U k t ∧ y ≠ x ∧ k = j) ∨ y ∈ free (T k) j u.
Proof.
setoid_rewrite (in_free_iff). introv hyp.
apply in_subst_upper in hyp.
destruct hyp as [hyp | hyp].
- destruct hyp. compare values j and k.
+ right. left. split; auto; split; auto.
intro contra; subst; contradiction.
+ auto.
- eauto using in_subst_upper.
Qed.
Corollary in_free_subst_upper_eq : ∀ k t u x y,
y ∈ free U k (t '{k | x ~> u}) →
(y ∈ free U k t ∧ y ≠ x) ∨ y ∈ free (T k) k u.
Proof.
introv hyp. apply in_free_subst_upper in hyp.
intuition.
Qed.
Corollary in_free_subst_upper_neq : ∀ k j t u x y,
k ≠ j →
y ∈ free U j (t '{k | x ~> u}) →
y ∈ free U j t ∨ y ∈ free (T k) j u.
Proof.
introv neq hyp. apply in_free_subst_upper in hyp.
intuition.
Qed.
Corollary FV_subst_upper : ∀ k j t u x y,
y `in` FV U j (t '{k | x ~> u}) →
k = j ∧ y `in` (FV U k t \\ {{x}} ∪ FV (T k) j u)%set ∨
k ≠ j ∧ y `in` (FV U j t ∪ FV (T k) j u)%set.
Proof.
setoid_rewrite AtomSet.union_spec.
setoid_rewrite AtomSet.diff_spec.
setoid_rewrite <- free_iff_FV.
introv hyp. apply in_free_subst_upper in hyp.
compare values j and k.
+ left. destruct hyp as [hyp | [hyp | hyp]].
{ split; auto. intuition. }
{ split; auto. left. split. intuition. fsetdec. }
{ split; auto. }
+ right. split; auto. destruct hyp as [hyp | [hyp | hyp]].
{ intuition. }
{ intuition. }
{ intuition. }
Qed.
Corollary FV_subst_upper_eq : ∀ k t u x,
FV U k (t '{k | x ~> u}) ⊆
(FV U k t \\ {{x}} ∪ FV (T k) k u).
Proof.
intros. intros a hyp. apply FV_subst_upper in hyp.
intuition.
Qed.
Corollary scoped_subst_eq : ∀ t k (u : T k LN) x γ1 γ2,
scoped U k t γ1 →
scoped (T k) k u γ2 →
scoped U k (t '{k | x ~> u}) (γ1 \\ {{x}} ∪ γ2).
Proof.
introv St Su. unfold scoped in ×.
etransitivity. apply FV_subst_upper_eq. fsetdec.
Qed.
Corollary FV_subst_upper_neq : ∀ k j t u x,
k ≠ j →
FV U j (t '{k | x ~> u}) ⊆
(FV U j t ∪ FV (T k) j u).
Proof.
intros. intros a hyp. apply FV_subst_upper in hyp.
intuition.
Qed.
Corollary scoped_subst_neq : ∀ t j k u x γ1 γ2,
j ≠ k →
scoped U k t γ1 →
scoped (T j) k u γ2 →
scoped U k (t '{j | x ~> u}) (γ1 ∪ γ2).
Proof.
introv St Su. unfold scoped in ×.
etransitivity. apply FV_subst_upper_neq; assumption.
fsetdec.
Qed.
Corollary in_subst_lower_eq : ∀ t k u l x,
(k, l) ∈m t ∧ l ≠ Fr x →
(k, l) ∈m t '{k | x ~> u}.
Proof with auto.
intros; rewrite in_subst_iff...
Qed.
Corollary in_subst_lower_neq : ∀ t k j u l x,
k ≠ j →
(j, l) ∈m t →
(j, l) ∈m t '{k | x ~> u}.
Proof with auto.
intros; rewrite in_subst_iff...
Qed.
Corollary in_free_subst_lower_eq : ∀ t k (u : T k LN) x y,
y ∈ free U k t ∧ y ≠ x →
y ∈ free U k (t '{k | x ~> u}).
Proof.
setoid_rewrite (in_free_iff). intros.
apply in_subst_lower_eq. now simpl_local.
Qed.
Corollary in_free_subst_lower_neq : ∀ t k j u x y,
k ≠ j →
y ∈ free U j t →
y ∈ free U j (t '{k | x ~> u}).
Proof.
setoid_rewrite (in_free_iff). intros.
now apply in_subst_lower_neq.
Qed.
Corollary FV_subst_lower_eq : ∀ t k (u : T k LN) x,
FV U k t \\ {{ x }} ⊆ FV U k (t '{k | x ~> u}).
Proof.
introv. intro a. rewrite AtomSet.diff_spec.
do 2 rewrite <- (free_iff_FV).
intros [? ?]. apply in_free_subst_lower_eq.
intuition.
Qed.
Corollary FV_subst_lower_eq_alt : ∀ t k (u : T k LN) x,
FV U k t ⊆ FV U k (t '{k | x ~> u}) ∪ {{ x }}.
Proof.
introv. intro a. rewrite AtomSet.union_spec.
do 2 rewrite <- (free_iff_FV).
destruct_eq_args a x.
- right. fsetdec.
- left. auto using in_free_subst_lower_eq.
Qed.
Corollary FV_subst_lower_neq : ∀ t k j u x,
k ≠ j →
FV U j t ⊆
FV U j (t '{k | x ~> u}).
Proof.
introv neq. intro a.
do 2 rewrite <- (free_iff_FV).
now apply in_free_subst_lower_neq.
Qed.
(j, l) ∈m t '{k | x ~> u} →
(j, l) ∈m t ∧ (j, l) ≠ (k, Fr x) ∨ (j, l) ∈m u.
Proof with auto.
introv hin. rewrite in_subst_iff in hin.
destruct hin as [[hyp1 hyp2] | [hyp | hyp] ].
- left. split; [assumption |]. injection...
- destruct hyp as [hyp1 [hyp2 hyp3]]. subst. left.
split; [assumption |]. injection...
- intuition.
Qed.
Corollary in_subst_upper_eq : ∀ k t u l x,
(k, l) ∈m t '{k | x ~> u} →
(k, l) ∈m t ∧ l ≠ Fr x ∨ (k, l) ∈m u.
Proof.
introv hyp. apply in_subst_upper in hyp.
autorewrite× with tea_local in hyp.
intuition.
Qed.
Corollary in_subst_upper_neq : ∀ k j t u l x,
k ≠ j →
(j, l) ∈m t '{k | x ~> u} →
(j, l) ∈m t ∨ (j, l) ∈m u.
Proof.
introv neq hyp. apply in_subst_upper in hyp.
intuition.
Qed.
Corollary in_free_subst_upper : ∀ k j t u x y,
y ∈ free U j (t '{k | x ~> u}) →
(y ∈ free U j t ∧ j ≠ k) ∨ (y ∈ free U k t ∧ y ≠ x ∧ k = j) ∨ y ∈ free (T k) j u.
Proof.
setoid_rewrite (in_free_iff). introv hyp.
apply in_subst_upper in hyp.
destruct hyp as [hyp | hyp].
- destruct hyp. compare values j and k.
+ right. left. split; auto; split; auto.
intro contra; subst; contradiction.
+ auto.
- eauto using in_subst_upper.
Qed.
Corollary in_free_subst_upper_eq : ∀ k t u x y,
y ∈ free U k (t '{k | x ~> u}) →
(y ∈ free U k t ∧ y ≠ x) ∨ y ∈ free (T k) k u.
Proof.
introv hyp. apply in_free_subst_upper in hyp.
intuition.
Qed.
Corollary in_free_subst_upper_neq : ∀ k j t u x y,
k ≠ j →
y ∈ free U j (t '{k | x ~> u}) →
y ∈ free U j t ∨ y ∈ free (T k) j u.
Proof.
introv neq hyp. apply in_free_subst_upper in hyp.
intuition.
Qed.
Corollary FV_subst_upper : ∀ k j t u x y,
y `in` FV U j (t '{k | x ~> u}) →
k = j ∧ y `in` (FV U k t \\ {{x}} ∪ FV (T k) j u)%set ∨
k ≠ j ∧ y `in` (FV U j t ∪ FV (T k) j u)%set.
Proof.
setoid_rewrite AtomSet.union_spec.
setoid_rewrite AtomSet.diff_spec.
setoid_rewrite <- free_iff_FV.
introv hyp. apply in_free_subst_upper in hyp.
compare values j and k.
+ left. destruct hyp as [hyp | [hyp | hyp]].
{ split; auto. intuition. }
{ split; auto. left. split. intuition. fsetdec. }
{ split; auto. }
+ right. split; auto. destruct hyp as [hyp | [hyp | hyp]].
{ intuition. }
{ intuition. }
{ intuition. }
Qed.
Corollary FV_subst_upper_eq : ∀ k t u x,
FV U k (t '{k | x ~> u}) ⊆
(FV U k t \\ {{x}} ∪ FV (T k) k u).
Proof.
intros. intros a hyp. apply FV_subst_upper in hyp.
intuition.
Qed.
Corollary scoped_subst_eq : ∀ t k (u : T k LN) x γ1 γ2,
scoped U k t γ1 →
scoped (T k) k u γ2 →
scoped U k (t '{k | x ~> u}) (γ1 \\ {{x}} ∪ γ2).
Proof.
introv St Su. unfold scoped in ×.
etransitivity. apply FV_subst_upper_eq. fsetdec.
Qed.
Corollary FV_subst_upper_neq : ∀ k j t u x,
k ≠ j →
FV U j (t '{k | x ~> u}) ⊆
(FV U j t ∪ FV (T k) j u).
Proof.
intros. intros a hyp. apply FV_subst_upper in hyp.
intuition.
Qed.
Corollary scoped_subst_neq : ∀ t j k u x γ1 γ2,
j ≠ k →
scoped U k t γ1 →
scoped (T j) k u γ2 →
scoped U k (t '{j | x ~> u}) (γ1 ∪ γ2).
Proof.
introv St Su. unfold scoped in ×.
etransitivity. apply FV_subst_upper_neq; assumption.
fsetdec.
Qed.
Corollary in_subst_lower_eq : ∀ t k u l x,
(k, l) ∈m t ∧ l ≠ Fr x →
(k, l) ∈m t '{k | x ~> u}.
Proof with auto.
intros; rewrite in_subst_iff...
Qed.
Corollary in_subst_lower_neq : ∀ t k j u l x,
k ≠ j →
(j, l) ∈m t →
(j, l) ∈m t '{k | x ~> u}.
Proof with auto.
intros; rewrite in_subst_iff...
Qed.
Corollary in_free_subst_lower_eq : ∀ t k (u : T k LN) x y,
y ∈ free U k t ∧ y ≠ x →
y ∈ free U k (t '{k | x ~> u}).
Proof.
setoid_rewrite (in_free_iff). intros.
apply in_subst_lower_eq. now simpl_local.
Qed.
Corollary in_free_subst_lower_neq : ∀ t k j u x y,
k ≠ j →
y ∈ free U j t →
y ∈ free U j (t '{k | x ~> u}).
Proof.
setoid_rewrite (in_free_iff). intros.
now apply in_subst_lower_neq.
Qed.
Corollary FV_subst_lower_eq : ∀ t k (u : T k LN) x,
FV U k t \\ {{ x }} ⊆ FV U k (t '{k | x ~> u}).
Proof.
introv. intro a. rewrite AtomSet.diff_spec.
do 2 rewrite <- (free_iff_FV).
intros [? ?]. apply in_free_subst_lower_eq.
intuition.
Qed.
Corollary FV_subst_lower_eq_alt : ∀ t k (u : T k LN) x,
FV U k t ⊆ FV U k (t '{k | x ~> u}) ∪ {{ x }}.
Proof.
introv. intro a. rewrite AtomSet.union_spec.
do 2 rewrite <- (free_iff_FV).
destruct_eq_args a x.
- right. fsetdec.
- left. auto using in_free_subst_lower_eq.
Qed.
Corollary FV_subst_lower_neq : ∀ t k j u x,
k ≠ j →
FV U j t ⊆
FV U j (t '{k | x ~> u}).
Proof.
introv neq. intro a.
do 2 rewrite <- (free_iff_FV).
now apply in_free_subst_lower_neq.
Qed.
Theorem subst_fresh : ∀ t k x u,
¬ x ∈ free U k t →
t '{k | x ~> u} = t.
Proof.
intros. apply (subst_id U). intros.
assert (Fr x ≠ l).
eapply (ninf_in_neq U); eauto.
now simpl_local.
Qed.
Corollary subst_fresh_set : ∀ t k x u,
¬ x `in` FV U k t →
t '{k | x ~> u} = t.
Proof.
setoid_rewrite <- free_iff_FV. apply subst_fresh.
Qed.
Theorem free_subst_fresh : ∀ t k j u x,
¬ x ∈ free U k t →
free U j (t '{k | x ~> u}) = free U j t.
Proof with auto.
introv fresh. replace (t '{k | x ~> u}) with t...
rewrite subst_fresh...
Qed.
Corollary free_subst_fresh_eq : ∀ t k u x,
¬ x ∈ free U k t →
free U k (t '{k | x ~> u}) = free U k t.
Proof.
introv fresh. replace (t '{k | x ~> u}) with t; auto.
now rewrite subst_fresh.
Qed.
Corollary FV_subst_fresh : ∀ t k j u x,
¬ x `in` FV U k t →
FV U j (t '{k | x ~> u}) [=] FV U j t.
Proof.
introv fresh. intro y.
rewrite <- ?(free_iff_FV) in ×.
now rewrite free_subst_fresh.
Qed.
Corollary FV_subst_fresh_eq : ∀ t k u x,
¬ x `in` FV U k t →
FV U k (t '{k | x ~> u}) [=] FV U k t.
Proof.
intros. apply FV_subst_fresh; auto.
Qed.
End fix_dtm.
¬ x ∈ free U k t →
t '{k | x ~> u} = t.
Proof.
intros. apply (subst_id U). intros.
assert (Fr x ≠ l).
eapply (ninf_in_neq U); eauto.
now simpl_local.
Qed.
Corollary subst_fresh_set : ∀ t k x u,
¬ x `in` FV U k t →
t '{k | x ~> u} = t.
Proof.
setoid_rewrite <- free_iff_FV. apply subst_fresh.
Qed.
Theorem free_subst_fresh : ∀ t k j u x,
¬ x ∈ free U k t →
free U j (t '{k | x ~> u}) = free U j t.
Proof with auto.
introv fresh. replace (t '{k | x ~> u}) with t...
rewrite subst_fresh...
Qed.
Corollary free_subst_fresh_eq : ∀ t k u x,
¬ x ∈ free U k t →
free U k (t '{k | x ~> u}) = free U k t.
Proof.
introv fresh. replace (t '{k | x ~> u}) with t; auto.
now rewrite subst_fresh.
Qed.
Corollary FV_subst_fresh : ∀ t k j u x,
¬ x `in` FV U k t →
FV U j (t '{k | x ~> u}) [=] FV U j t.
Proof.
introv fresh. intro y.
rewrite <- ?(free_iff_FV) in ×.
now rewrite free_subst_fresh.
Qed.
Corollary FV_subst_fresh_eq : ∀ t k u x,
¬ x `in` FV U k t →
FV U k (t '{k | x ~> u}) [=] FV U k t.
Proof.
intros. apply FV_subst_fresh; auto.
Qed.
End fix_dtm.
Section fix_dtm.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Lemma subst_subst_neq_loc : ∀ j k1 k2 (u1 : T k1 LN) (u2 : T k2 LN) (x1 x2 : atom),
k1 ≠ k2 →
¬ x1 ∈ free (T k2) k1 u2 →
subst (T j) k2 x2 u2 ∘ btg k1 (subst_loc k1 x1 u1) j =
subst (T j) k1 x1 (subst (T k1) k2 x2 u2 u1) ∘ btg k2 (subst_loc k2 x2 u2) j.
Proof with easy.
intros. ext l. unfold compose. compare j to both of { k1 k2 }.
- do 2 simpl_tgt_fallback.
simpl_local.
compare l to atom x1.
+ rewrite 2(subst_loc_eq)...
+ rewrite subst_loc_neq; auto. now simpl_local.
+ rewrite subst_loc_b. now simpl_local.
- simpl_tgt. simpl_local. compare l to atom x2.
+ simpl_local. rewrite (subst_fresh (T k2))...
+ simpl_local...
+ simpl_local...
- simpl_tgt_fallback. now do 2 (rewrite subst_in_mret_neq; auto).
Qed.
Theorem subst_subst_neq : ∀ k1 k2 u1 u2 t (x1 x2 : atom),
k1 ≠ k2 →
¬ x1 ∈ free (T k2) k1 u2 →
t '{k1 | x1 ~> u1} '{k2 | x2 ~> u2} =
t '{k2 | x2 ~> u2} '{k1 | x1 ~> u1 '{k2 | x2 ~> u2} }.
Proof.
intros. unfold subst.
compose near t on left.
compose near t on right.
unfold kbind. rewrite 2(mbind_mbind U).
fequal. ext j. now apply subst_subst_neq_loc.
Qed.
Lemma subst_subst_eq_local : ∀ k u1 u2 x1 x2,
¬ x1 ∈ free (T k) k u2 →
x1 ≠ x2 →
subst (T k) k x2 u2 ∘ subst_loc k x1 u1 =
subst (T k) k x1 (subst (T k) k x2 u2 u1) ∘ subst_loc k x2 u2.
Proof with auto.
intros. ext l. unfold compose. compare l to atom x1.
- rewrite subst_loc_eq, subst_loc_neq,
subst_in_mret_eq, subst_loc_eq...
- rewrite subst_loc_neq...
compare values x2 and a.
+ rewrite subst_in_mret_eq, subst_loc_eq, (subst_fresh (T k))...
+ rewrite subst_loc_neq, 2(subst_in_mret_eq), 2(subst_loc_neq)...
- rewrite 2(subst_loc_b), 2(subst_in_mret_eq), 2(subst_loc_b)...
Qed.
Theorem subst_subst_eq : ∀ k u1 u2 t x1 x2,
¬ x1 ∈ free (T k) k u2 →
x1 ≠ x2 →
t '{k | x1 ~> u1} '{k | x2 ~> u2} =
t '{k | x2 ~> u2} '{k | x1 ~> u1 '{k | x2 ~> u2} }.
Proof with auto.
intros. unfold subst.
compose near t.
rewrite 2(kbind_kbind U).
fequal. now apply subst_subst_eq_local.
Qed.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Lemma subst_subst_neq_loc : ∀ j k1 k2 (u1 : T k1 LN) (u2 : T k2 LN) (x1 x2 : atom),
k1 ≠ k2 →
¬ x1 ∈ free (T k2) k1 u2 →
subst (T j) k2 x2 u2 ∘ btg k1 (subst_loc k1 x1 u1) j =
subst (T j) k1 x1 (subst (T k1) k2 x2 u2 u1) ∘ btg k2 (subst_loc k2 x2 u2) j.
Proof with easy.
intros. ext l. unfold compose. compare j to both of { k1 k2 }.
- do 2 simpl_tgt_fallback.
simpl_local.
compare l to atom x1.
+ rewrite 2(subst_loc_eq)...
+ rewrite subst_loc_neq; auto. now simpl_local.
+ rewrite subst_loc_b. now simpl_local.
- simpl_tgt. simpl_local. compare l to atom x2.
+ simpl_local. rewrite (subst_fresh (T k2))...
+ simpl_local...
+ simpl_local...
- simpl_tgt_fallback. now do 2 (rewrite subst_in_mret_neq; auto).
Qed.
Theorem subst_subst_neq : ∀ k1 k2 u1 u2 t (x1 x2 : atom),
k1 ≠ k2 →
¬ x1 ∈ free (T k2) k1 u2 →
t '{k1 | x1 ~> u1} '{k2 | x2 ~> u2} =
t '{k2 | x2 ~> u2} '{k1 | x1 ~> u1 '{k2 | x2 ~> u2} }.
Proof.
intros. unfold subst.
compose near t on left.
compose near t on right.
unfold kbind. rewrite 2(mbind_mbind U).
fequal. ext j. now apply subst_subst_neq_loc.
Qed.
Lemma subst_subst_eq_local : ∀ k u1 u2 x1 x2,
¬ x1 ∈ free (T k) k u2 →
x1 ≠ x2 →
subst (T k) k x2 u2 ∘ subst_loc k x1 u1 =
subst (T k) k x1 (subst (T k) k x2 u2 u1) ∘ subst_loc k x2 u2.
Proof with auto.
intros. ext l. unfold compose. compare l to atom x1.
- rewrite subst_loc_eq, subst_loc_neq,
subst_in_mret_eq, subst_loc_eq...
- rewrite subst_loc_neq...
compare values x2 and a.
+ rewrite subst_in_mret_eq, subst_loc_eq, (subst_fresh (T k))...
+ rewrite subst_loc_neq, 2(subst_in_mret_eq), 2(subst_loc_neq)...
- rewrite 2(subst_loc_b), 2(subst_in_mret_eq), 2(subst_loc_b)...
Qed.
Theorem subst_subst_eq : ∀ k u1 u2 t x1 x2,
¬ x1 ∈ free (T k) k u2 →
x1 ≠ x2 →
t '{k | x1 ~> u1} '{k | x2 ~> u2} =
t '{k | x2 ~> u2} '{k | x1 ~> u1 '{k | x2 ~> u2} }.
Proof with auto.
intros. unfold subst.
compose near t.
rewrite 2(kbind_kbind U).
fequal. now apply subst_subst_eq_local.
Qed.
Corollary subst_subst_comm_eq : ∀ k u1 u2 t x1 x2,
x1 ≠ x2 →
¬ x1 ∈ free (T k) k u2 →
¬ x2 ∈ free (T k) k u1 →
t '{k | x1 ~> u1} '{k | x2 ~> u2} =
t '{k | x2 ~> u2} '{k | x1 ~> u1}.
Proof.
intros. rewrite subst_subst_eq; auto.
rewrite (subst_fresh (T k)); auto.
Qed.
Corollary subst_subst_comm_neq : ∀ k1 k2 u1 u2 t x1 x2,
k1 ≠ k2 →
¬ x1 ∈ free (T k2) k1 u2 →
¬ x2 ∈ free (T k1) k2 u1 →
t '{k1 | x1 ~> u1} '{k2 | x2 ~> u2} =
t '{k2 | x2 ~> u2} '{k1 | x1 ~> u1}.
Proof.
intros. rewrite subst_subst_neq; auto.
rewrite (subst_fresh (T k1)); auto.
Qed.
x1 ≠ x2 →
¬ x1 ∈ free (T k) k u2 →
¬ x2 ∈ free (T k) k u1 →
t '{k | x1 ~> u1} '{k | x2 ~> u2} =
t '{k | x2 ~> u2} '{k | x1 ~> u1}.
Proof.
intros. rewrite subst_subst_eq; auto.
rewrite (subst_fresh (T k)); auto.
Qed.
Corollary subst_subst_comm_neq : ∀ k1 k2 u1 u2 t x1 x2,
k1 ≠ k2 →
¬ x1 ∈ free (T k2) k1 u2 →
¬ x2 ∈ free (T k1) k2 u1 →
t '{k1 | x1 ~> u1} '{k2 | x2 ~> u2} =
t '{k2 | x2 ~> u2} '{k1 | x1 ~> u1}.
Proof.
intros. rewrite subst_subst_neq; auto.
rewrite (subst_fresh (T k1)); auto.
Qed.
Theorem subst_lc_eq : ∀ k u t x,
LC U k t →
LC (T k) k u →
LC U k (subst U k x u t).
Proof.
unfold LC. introv lct lcu hin.
rewrite (inmd_subst_iff_eq' U) in hin.
destruct hin as [[? ?] | [n1 [n2 [h1 [h2 h3]]]]].
- auto.
- subst. specialize (lcu n2 l h2).
unfold lc_loc in ×.
destruct l; auto. unfold_monoid.
rewrite countk_app. lia.
Qed.
Theorem subst_lc_neq : ∀ k j u t x,
k ≠ j →
LC U j t →
LC (T k) j u →
LC U j (subst U k x u t).
Proof.
unfold LC. introv neq lct lcu hin.
rewrite (inmd_subst_iff_neq' U) in hin; auto.
destruct hin as [? | [n1 [n2 [h1 [h2 h3]]]]].
- auto.
- subst. specialize (lcu n2 l h2).
unfold lc_loc in ×.
destruct l; auto. unfold_monoid.
rewrite countk_app. lia.
Qed.
LC U k t →
LC (T k) k u →
LC U k (subst U k x u t).
Proof.
unfold LC. introv lct lcu hin.
rewrite (inmd_subst_iff_eq' U) in hin.
destruct hin as [[? ?] | [n1 [n2 [h1 [h2 h3]]]]].
- auto.
- subst. specialize (lcu n2 l h2).
unfold lc_loc in ×.
destruct l; auto. unfold_monoid.
rewrite countk_app. lia.
Qed.
Theorem subst_lc_neq : ∀ k j u t x,
k ≠ j →
LC U j t →
LC (T k) j u →
LC U j (subst U k x u t).
Proof.
unfold LC. introv neq lct lcu hin.
rewrite (inmd_subst_iff_neq' U) in hin; auto.
destruct hin as [? | [n1 [n2 [h1 [h2 h3]]]]].
- auto.
- subst. specialize (lcu n2 l h2).
unfold lc_loc in ×.
destruct l; auto. unfold_monoid.
rewrite countk_app. lia.
Qed.
Lemma subst_spec_local : ∀ k u w l x,
subst_loc k x u l =
open_loc k u (w, (close_loc k x) (w, l)).
Proof.
introv. compare l to atom x; autorewrite× with tea_local.
- cbn. compare values x and x. unfold id.
compare naturals (countk k w) and (countk k w).
- cbn. compare values x and a. (* todo fix fragile names *)
- cbn. unfold id. compare naturals n and (countk k w).
compare naturals (Datatypes.S (countk k w)) and (countk k w).
now compare naturals (Datatypes.S n) and (countk k w).
Qed.
Theorem subst_spec : ∀ k x u t,
t '{k | x ~> u} = ('[k | x] t) '(k | u).
Proof.
intros. compose near t on right.
unfold open, close, subst.
rewrite (kbindd_kmapd U).
symmetry. apply (kbindd_respectful_kbind k).
symmetry. apply subst_spec_local.
Qed.
subst_loc k x u l =
open_loc k u (w, (close_loc k x) (w, l)).
Proof.
introv. compare l to atom x; autorewrite× with tea_local.
- cbn. compare values x and x. unfold id.
compare naturals (countk k w) and (countk k w).
- cbn. compare values x and a. (* todo fix fragile names *)
- cbn. unfold id. compare naturals n and (countk k w).
compare naturals (Datatypes.S (countk k w)) and (countk k w).
now compare naturals (Datatypes.S n) and (countk k w).
Qed.
Theorem subst_spec : ∀ k x u t,
t '{k | x ~> u} = ('[k | x] t) '(k | u).
Proof.
intros. compose near t on right.
unfold open, close, subst.
rewrite (kbindd_kmapd U).
symmetry. apply (kbindd_respectful_kbind k).
symmetry. apply subst_spec_local.
Qed.
Definition subst_loc_LN k x (u : LN) : LN → LN :=
fun l ⇒ match l with
| Fr y ⇒ if x == y then u else Fr y
| Bd n ⇒ Bd n
end.
Theorem subst_by_LN_spec : ∀ k x l,
subst U k x (mret T k l) = kmap U k (subst_loc_LN k x l).
Proof.
intros. unfold subst. ext t.
apply kbind_respectful_kmap.
intros l' Hin. destruct l'.
- cbn. compare values x and n.
- reflexivity.
Qed.
fun l ⇒ match l with
| Fr y ⇒ if x == y then u else Fr y
| Bd n ⇒ Bd n
end.
Theorem subst_by_LN_spec : ∀ k x l,
subst U k x (mret T k l) = kmap U k (subst_loc_LN k x l).
Proof.
intros. unfold subst. ext t.
apply kbind_respectful_kmap.
intros l' Hin. destruct l'.
- cbn. compare values x and n.
- reflexivity.
Qed.
Theorem subst_same : ∀ t k x,
t '{k | x ~> mret T k (Fr x)} = t.
Proof.
intros. apply (subst_id U).
intros. compare l to atom x; now simpl_local.
Qed.
End fix_dtm.
End subst_metatheory.
t '{k | x ~> mret T k (Fr x)} = t.
Proof.
intros. apply (subst_id U).
intros. compare l to atom x; now simpl_local.
Qed.
End fix_dtm.
End subst_metatheory.
Section close_metatheory.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Lemma in_free_close_iff_loc_1 : ∀ k w l t x y,
(w, k, l) ∈md t →
Fr y = close_loc k x (w, l) →
(k, Fr y) ∈m t ∧ x ≠ y.
Proof.
introv lin heq. destruct l as [la | ln].
- cbn in heq. destruct_eq_args x la.
inversion heq.
now apply (inmd_implies_in U) in lin.
- cbn in heq. compare_nats_args ln (countk k w); discriminate.
Qed.
Lemma in_free_close_iff_loc_2 : ∀ t k x y,
x ≠ y →
(k, Fr y) ∈m t →
∃ w l, (w, k, l) ∈md t ∧ Fr y = close_loc k x (w, l).
Proof.
introv neq yin. apply (inmd_iff_in U) in yin. destruct yin as [w yin].
∃ w. ∃ (Fr y). cbn. compare values x and y.
Qed.
Theorem in_free_close_iff : ∀ k t x y,
y ∈ free U k ('[k | x] t) ↔ y ∈ free U k t ∧ x ≠ y.
Proof.
introv. rewrite (free_close_eq_iff U).
rewrite (in_free_iff). split.
- introv [? [? [? ?] ] ]. eauto using in_free_close_iff_loc_1.
- intros [? ?]. eauto using in_free_close_iff_loc_2.
Qed.
Corollary in_free_close_iff_1 : ∀ k t x y,
y ≠ x →
y ∈ free U k ('[k | x] t) ↔ y ∈ free U k t.
Proof.
intros. rewrite in_free_close_iff. intuition.
Qed.
Corollary FV_close : ∀ k t x,
FV U k ('[k | x] t) [=] FV U k t \\ {{ x }}.
Proof.
introv. intro a. rewrite AtomSet.diff_spec.
rewrite <- 2(free_iff_FV). rewrite in_free_close_iff.
fsetdec.
Qed.
Corollary nin_free_close : ∀ k t x,
¬ (x ∈ free U k ('[k | x] t)).
Proof.
introv. rewrite in_free_close_iff. intuition.
Qed.
Corollary nin_FV_close : ∀ k t x,
¬ (x `in` FV U k ('[k | x] t)).
Proof.
introv. rewrite <- free_iff_FV. apply nin_free_close.
Qed.
(w, k, l) ∈md t →
Fr y = close_loc k x (w, l) →
(k, Fr y) ∈m t ∧ x ≠ y.
Proof.
introv lin heq. destruct l as [la | ln].
- cbn in heq. destruct_eq_args x la.
inversion heq.
now apply (inmd_implies_in U) in lin.
- cbn in heq. compare_nats_args ln (countk k w); discriminate.
Qed.
Lemma in_free_close_iff_loc_2 : ∀ t k x y,
x ≠ y →
(k, Fr y) ∈m t →
∃ w l, (w, k, l) ∈md t ∧ Fr y = close_loc k x (w, l).
Proof.
introv neq yin. apply (inmd_iff_in U) in yin. destruct yin as [w yin].
∃ w. ∃ (Fr y). cbn. compare values x and y.
Qed.
Theorem in_free_close_iff : ∀ k t x y,
y ∈ free U k ('[k | x] t) ↔ y ∈ free U k t ∧ x ≠ y.
Proof.
introv. rewrite (free_close_eq_iff U).
rewrite (in_free_iff). split.
- introv [? [? [? ?] ] ]. eauto using in_free_close_iff_loc_1.
- intros [? ?]. eauto using in_free_close_iff_loc_2.
Qed.
Corollary in_free_close_iff_1 : ∀ k t x y,
y ≠ x →
y ∈ free U k ('[k | x] t) ↔ y ∈ free U k t.
Proof.
intros. rewrite in_free_close_iff. intuition.
Qed.
Corollary FV_close : ∀ k t x,
FV U k ('[k | x] t) [=] FV U k t \\ {{ x }}.
Proof.
introv. intro a. rewrite AtomSet.diff_spec.
rewrite <- 2(free_iff_FV). rewrite in_free_close_iff.
fsetdec.
Qed.
Corollary nin_free_close : ∀ k t x,
¬ (x ∈ free U k ('[k | x] t)).
Proof.
introv. rewrite in_free_close_iff. intuition.
Qed.
Corollary nin_FV_close : ∀ k t x,
¬ (x `in` FV U k ('[k | x] t)).
Proof.
introv. rewrite <- free_iff_FV. apply nin_free_close.
Qed.
Theorem close_lc_eq : ∀ k t x,
LC U k t →
LCn U k 1 (close U k x t).
Proof.
unfold LC. introv lct hin.
rewrite (inmd_close_iff_eq U) in hin.
destruct hin as [l1 [? ?]]. compare l1 to atom x; subst.
- cbn. compare values x and x. unfold_monoid; lia.
- cbn. compare values x and a.
- cbn. compare naturals n and (countk k w).
+ specialize (lct w (Bd (countk k w)) ltac:(assumption)).
cbn in lct. now unfold_monoid; lia.
+ specialize (lct w (Bd n) ltac:(assumption)).
cbn in lct. now unfold_monoid; lia.
Qed.
Theorem close_lc_neq : ∀ k j t x,
k ≠ j →
LC U j t →
LC U j (close U k x t).
Proof.
unfold LC. introv neq lct hin.
rewrite (inmd_close_neq_iff U) in hin; auto.
Qed.
End close_metatheory.
LC U k t →
LCn U k 1 (close U k x t).
Proof.
unfold LC. introv lct hin.
rewrite (inmd_close_iff_eq U) in hin.
destruct hin as [l1 [? ?]]. compare l1 to atom x; subst.
- cbn. compare values x and x. unfold_monoid; lia.
- cbn. compare values x and a.
- cbn. compare naturals n and (countk k w).
+ specialize (lct w (Bd (countk k w)) ltac:(assumption)).
cbn in lct. now unfold_monoid; lia.
+ specialize (lct w (Bd n) ltac:(assumption)).
cbn in lct. now unfold_monoid; lia.
Qed.
Theorem close_lc_neq : ∀ k j t x,
k ≠ j →
LC U j t →
LC U j (close U k x t).
Proof.
unfold LC. introv neq lct hin.
rewrite (inmd_close_neq_iff U) in hin; auto.
Qed.
End close_metatheory.
Section open_metatheory.
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Context
(U : Type → Type)
`{MultiDecoratedTraversablePreModule (list K) T U (mn_op := Monoid_op_list) (mn_unit := Monoid_unit_list)}
`{! MultiDecoratedTraversableMonad (list K) T}.
Implicit Types
(k : K) (j : K)
(l : LN) (p : LN)
(x : atom) (t : U LN)
(w : list K) (n : nat).
Lemma free_open_upper_local : ∀ t k j (u : T k LN) w l x,
(k, l) ∈m t →
x ∈ free (T k) j (open_loc k u (w, l)) →
k = j ∧ l = Fr x ∧ x ∈ free U j t ∨
x ∈ free (T k) j u.
Proof with auto.
introv lin xin. rewrite in_free_iff in xin.
rewrite 2(in_free_iff). destruct l as [y | n].
- left. autorewrite with tea_local in xin.
destruct xin; subst.
tauto.
- right. cbn in xin. compare naturals n and (countk k w).
{ contradict xin. simpl_local. intuition. }
{ assumption. }
{ contradict xin. simpl_local. intuition. }
Qed.
Corollary free_open_upper_local_eq : ∀ t k (u : T k LN) w l x,
(k, l) ∈m t →
x ∈ free (T k) k (open_loc k u (w, l)) →
x ∈ free U k t ∨ x ∈ free (T k) k u.
Proof.
introv lin xin.
apply free_open_upper_local
with (t:=t) in xin; auto.
intuition.
Qed.
Corollary free_open_upper_local_neq : ∀ t k j (u : T k LN) w l x,
k ≠ j →
(k, l) ∈m t →
x ∈ free (T k) j (open_loc k u (w, l)) →
x ∈ free (T k) j u.
Proof.
introv neq lin xin.
apply free_open_upper_local
with (t:=t) in xin; auto.
intuition.
Qed.
Theorem free_open_upper : ∀ t k j (u : T k LN) x,
x ∈ free U j (t '(k | u)) →
x ∈ free U j t ∨ x ∈ free (T k) j u.
Proof.
introv xin. compare values j and k.
- rewrite (free_open_eq_iff U) in xin.
destruct xin as [w [l [hin ?]]].
eapply (inmd_implies_in U) in hin.
eauto using free_open_upper_local_eq.
- rewrite (free_open_neq_iff U) in xin; auto.
destruct xin as [? | [w [l [hin ?]]]].
auto. apply (inmd_implies_in U) in hin.
right. eauto using free_open_upper_local_neq.
Qed.
Corollary FV_open_upper : ∀ t k j (u : T k LN),
FV U j (t '(k | u)) ⊆ FV U j t ∪ FV (T k) j u.
Proof.
intros. intro a. rewrite AtomSet.union_spec.
repeat rewrite <- (free_iff_FV).
auto using free_open_upper.
Qed.
Corollary free_open_upper_eq : ∀ t k (u : T k LN) x,
x ∈ free U k (t '(k | u)) →
x ∈ free U k t ∨ x ∈ free (T k) k u.
Proof.
intros. auto using free_open_upper.
Qed.
Corollary FV_open_upper_eq : ∀ t k (u : T k LN),
FV U k (t '(k | u)) ⊆ FV U k t ∪ FV (T k) k u.
Proof.
intros. apply FV_open_upper.
Qed.
Theorem free_open_lower : ∀ t k j u x,
x ∈ free U j t →
x ∈ free U j (t '(k | u)).
Proof.
introv xin. compare values j and k.
- rewrite (in_free_iff) in xin.
rewrite (inmd_iff_in U) in xin.
destruct xin as [w xin].
rewrite (free_open_eq_iff U).
setoid_rewrite (in_free_iff).
∃ w. ∃ (Fr x).
now autorewrite with tea_local.
- rewrite (free_open_neq_iff U); auto.
Qed.
Theorem free_open_lower_eq : ∀ t k u x,
x ∈ free U k t →
x ∈ free U k (t '(k | u)).
Proof.
intros. auto using free_open_lower.
Qed.
Corollary FV_open_lower : ∀ t k j u,
FV U j t ⊆ FV U j (t '(k | u)).
Proof.
intros. intro a. rewrite <- 2(free_iff_FV).
apply free_open_lower.
Qed.
Corollary FV_open_lower_eq : ∀ t k u,
FV U k t ⊆ FV U k (t '(k | u)).
Proof.
intros. apply FV_open_lower.
Qed.
(k, l) ∈m t →
x ∈ free (T k) j (open_loc k u (w, l)) →
k = j ∧ l = Fr x ∧ x ∈ free U j t ∨
x ∈ free (T k) j u.
Proof with auto.
introv lin xin. rewrite in_free_iff in xin.
rewrite 2(in_free_iff). destruct l as [y | n].
- left. autorewrite with tea_local in xin.
destruct xin; subst.
tauto.
- right. cbn in xin. compare naturals n and (countk k w).
{ contradict xin. simpl_local. intuition. }
{ assumption. }
{ contradict xin. simpl_local. intuition. }
Qed.
Corollary free_open_upper_local_eq : ∀ t k (u : T k LN) w l x,
(k, l) ∈m t →
x ∈ free (T k) k (open_loc k u (w, l)) →
x ∈ free U k t ∨ x ∈ free (T k) k u.
Proof.
introv lin xin.
apply free_open_upper_local
with (t:=t) in xin; auto.
intuition.
Qed.
Corollary free_open_upper_local_neq : ∀ t k j (u : T k LN) w l x,
k ≠ j →
(k, l) ∈m t →
x ∈ free (T k) j (open_loc k u (w, l)) →
x ∈ free (T k) j u.
Proof.
introv neq lin xin.
apply free_open_upper_local
with (t:=t) in xin; auto.
intuition.
Qed.
Theorem free_open_upper : ∀ t k j (u : T k LN) x,
x ∈ free U j (t '(k | u)) →
x ∈ free U j t ∨ x ∈ free (T k) j u.
Proof.
introv xin. compare values j and k.
- rewrite (free_open_eq_iff U) in xin.
destruct xin as [w [l [hin ?]]].
eapply (inmd_implies_in U) in hin.
eauto using free_open_upper_local_eq.
- rewrite (free_open_neq_iff U) in xin; auto.
destruct xin as [? | [w [l [hin ?]]]].
auto. apply (inmd_implies_in U) in hin.
right. eauto using free_open_upper_local_neq.
Qed.
Corollary FV_open_upper : ∀ t k j (u : T k LN),
FV U j (t '(k | u)) ⊆ FV U j t ∪ FV (T k) j u.
Proof.
intros. intro a. rewrite AtomSet.union_spec.
repeat rewrite <- (free_iff_FV).
auto using free_open_upper.
Qed.
Corollary free_open_upper_eq : ∀ t k (u : T k LN) x,
x ∈ free U k (t '(k | u)) →
x ∈ free U k t ∨ x ∈ free (T k) k u.
Proof.
intros. auto using free_open_upper.
Qed.
Corollary FV_open_upper_eq : ∀ t k (u : T k LN),
FV U k (t '(k | u)) ⊆ FV U k t ∪ FV (T k) k u.
Proof.
intros. apply FV_open_upper.
Qed.
Theorem free_open_lower : ∀ t k j u x,
x ∈ free U j t →
x ∈ free U j (t '(k | u)).
Proof.
introv xin. compare values j and k.
- rewrite (in_free_iff) in xin.
rewrite (inmd_iff_in U) in xin.
destruct xin as [w xin].
rewrite (free_open_eq_iff U).
setoid_rewrite (in_free_iff).
∃ w. ∃ (Fr x).
now autorewrite with tea_local.
- rewrite (free_open_neq_iff U); auto.
Qed.
Theorem free_open_lower_eq : ∀ t k u x,
x ∈ free U k t →
x ∈ free U k (t '(k | u)).
Proof.
intros. auto using free_open_lower.
Qed.
Corollary FV_open_lower : ∀ t k j u,
FV U j t ⊆ FV U j (t '(k | u)).
Proof.
intros. intro a. rewrite <- 2(free_iff_FV).
apply free_open_lower.
Qed.
Corollary FV_open_lower_eq : ∀ t k u,
FV U k t ⊆ FV U k (t '(k | u)).
Proof.
intros. apply FV_open_lower.
Qed.
Lemma open_lc_local : ∀ k (u : T k LN) w l,
lc_loc k 0 (w, l) →
open_loc k u (w, l) = mret T k l.
Proof.
introv hyp. destruct l as [a | n].
- reflexivity.
- cbn in ×. compare naturals n and (countk k w); unfold_monoid; lia.
Qed.
Lemma open_lc : ∀ k t u,
LC U k t →
t '(k | u) = t.
Proof.
introv lc. apply (open_id U). introv lin.
specialize (lc _ _ lin).
destruct l; auto using open_lc_local.
Qed.
lc_loc k 0 (w, l) →
open_loc k u (w, l) = mret T k l.
Proof.
introv hyp. destruct l as [a | n].
- reflexivity.
- cbn in ×. compare naturals n and (countk k w); unfold_monoid; lia.
Qed.
Lemma open_lc : ∀ k t u,
LC U k t →
t '(k | u) = t.
Proof.
introv lc. apply (open_id U). introv lin.
specialize (lc _ _ lin).
destruct l; auto using open_lc_local.
Qed.
Lemma subst_open_eq_loc : ∀ k u1 u2 x,
LC (T k) k u2 →
subst (T k) k x u2 ∘ open_loc k u1 =
open_loc k (u1 '{k | x ~> u2}) ⋆kdm (subst_loc k x u2 ∘ snd).
Proof.
introv lcu2. ext [w l]. unfold compose_kdm.
unfold compose. compare l to atom x.
- cbn. simpl_local. compare values x and x.
symmetry. apply kbindd_respectful_id. intros ? [?|?] hin.
+ trivial.
+ specialize (lcu2 _ _ hin). cbn in lcu2. cbn. unfold_monoid.
rewrite countk_app.
compare naturals n and (countk k w + countk k w0).
- cbn. simpl_local. compare values x and a.
now rewrite (kbindd_comp_mret_eq).
(* <<< TODO standardize this lemma *)
- cbn. rewrite (kbindd_comp_mret_eq).
compare naturals n and (countk k w); cbn; simpl_local.
+ rewrite monoid_id_r. compare naturals n and (countk k w).
+ rewrite monoid_id_r. cbn. compare naturals (countk k w) and (countk k w).
+ rewrite monoid_id_r. cbn. compare naturals n and (countk k w).
Qed.
Theorem subst_open_eq : ∀ k u1 u2 t x,
LC (T k) k u2 →
t '(k | u1) '{k | x ~> u2} =
t '{k | x ~> u2} '(k | u1 '{k | x ~> u2}).
Proof.
introv lc. compose near t.
unfold open, subst at 1 3.
rewrite (kbind_kbindd U), (kbindd_kbind U).
fequal. apply subst_open_eq_loc; auto.
Qed.
Theorem subst_open_neq_loc : ∀ k1 k2 (u1 : T k1 LN) (u2 : T k2 LN) (x : atom),
k1 ≠ k2 →
LC (T k2) k1 u2 →
(btgd k2 (subst_loc k2 x u2 ∘ extract (W := prod (list K)))) ⋆dm btgd k1 (open_loc k1 u1) =
(btgd k1 (open_loc k1 (mbind (T k1) (btg k2 (subst_loc k2 x u2)) u1))) ⋆dm (btg k2 (subst_loc k2 x u2) ◻ const (extract (W := prod (list K)))).
Proof.
introv Hneq HLC. ext j [w l].
unfold compose_dm.
compare values j and k1.
{ (* j = k1 *)
rewrite btgd_eq.
replace ((btg k2 (subst_loc k2 x u2) ◻ const extract) k1 (w, l))
with (btg k2 (subst_loc k2 x u2) k1 l) by (compare values k1 and k1).
rewrite btg_neq; auto.
compose near l on right.
rewrite mbindd_comp_mret.
unfold vec_compose at 2.
unfold allK at 2, const.
unfold compose at 2 3.
rewrite btgd_eq.
replace (incr w (ret l)) with (w, l).
2:{ cbn; now simpl_monoid. }
cbn. destruct l.
- compose near (Fr n) on left;
rewrite mbindd_comp_mret;
unfold compose; cbn;
compare values k1 and k2.
- compare naturals n and (countk k1 w).
+ compose near (Bd n) on left.
rewrite mbindd_comp_mret;
unfold compose; cbn;
compare values k1 and k2.
+ unfold mbind; fequal.
unfold vec_compose, allK, const.
ext j.
destruct_eq_args j k2.
× rewrite btg_eq, btgd_eq.
reassociate →.
replace (extract ∘ incr w) with (extract (W := prod (list K)) (A := LN)).
reflexivity.
symmetry; apply (extract_incr (A := LN) w).
× rewrite btgd_neq; auto.
rewrite btg_neq; auto.
reassociate →.
replace (extract ∘ incr w) with (extract (W := prod (list K)) (A := LN)).
reflexivity.
symmetry; apply (extract_incr (A := LN) w).
+ compose near (Bd (n - 1)) on left.
rewrite mbindd_comp_mret;
unfold compose; cbn;
compare values k1 and k2.
}
{ (* j <> k1 *)
rewrite btgd_neq; auto.
unfold vec_compose, const, compose.
cbn. compose near l on left.
rewrite mbindd_comp_mret.
compare values j and k2.
{ (* j = k2 *)
rewrite btgd_eq.
rewrite btg_eq.
unfold compose, allK, const. cbn.
compare l to atom x.
- (* l = Fr x *)
cbn. destruct_eq_args x x.
symmetry.
apply mbindd_respectful_id.
intros w' k l Hin.
compare values k and k1.
+ (* k = k1 *)
unfold LC, LCn in HLC.
specialize (HLC _ _ Hin).
unfold lc_loc in HLC.
destruct l.
{ cbn. compare values k1 and k1.
now destruct DESTR_EQ0.
}
{ rewrite btgd_eq.
cbn. unfold_ops @Monoid_op_list.
rewrite countk_app.
compare naturals n and (countk k1 w + countk k1 w'). }
+ (* k <> k1 *)
rewrite btgd_neq; auto.
- rewrite subst_loc_fr_neq.
compose near (Fr a) on right.
rewrite mbindd_comp_mret.
rewrite btgd_neq; auto.
inversion 1. congruence.
- cbn. compose near (Bd n) on right.
rewrite mbindd_comp_mret.
rewrite btgd_neq; auto.
}
{ (* j <> k2 *)
rewrite btgd_neq; auto.
rewrite btg_neq; auto.
compose near l on right.
rewrite (mbindd_comp_mret).
rewrite btgd_neq; auto. }
}
Qed.
Theorem subst_open_neq : ∀ k1 k2 (u1 : T k1 LN) (u2 : T k2 LN) (x : atom) (t : U LN),
k1 ≠ k2 →
LC (T k2) k1 u2 →
t '(k1 | u1) '{k2 | x ~> u2} =
t '{k2 | x ~> u2} '(k1 | u1 '{k2 | x ~> u2}).
Proof.
introv neq lc. compose near t.
unfold subst, open.
unfold kbind, kbindd.
rewrite (mbind_to_mbindd U), (mbindd_mbindd U).
rewrite (mbindd_mbindd U).
fequal.
pose (lemma := subst_open_neq_loc).
unfold compose_dm in lemma. setoid_rewrite <- lemma; auto.
ext k [w a]. unfold vec_compose.
fequal. ext j [w' a']. compare values j and k2.
+ rewrite btgd_eq, btg_eq. cbn. reflexivity.
+ rewrite btgd_neq, btg_neq; auto.
Qed.
LC (T k) k u2 →
subst (T k) k x u2 ∘ open_loc k u1 =
open_loc k (u1 '{k | x ~> u2}) ⋆kdm (subst_loc k x u2 ∘ snd).
Proof.
introv lcu2. ext [w l]. unfold compose_kdm.
unfold compose. compare l to atom x.
- cbn. simpl_local. compare values x and x.
symmetry. apply kbindd_respectful_id. intros ? [?|?] hin.
+ trivial.
+ specialize (lcu2 _ _ hin). cbn in lcu2. cbn. unfold_monoid.
rewrite countk_app.
compare naturals n and (countk k w + countk k w0).
- cbn. simpl_local. compare values x and a.
now rewrite (kbindd_comp_mret_eq).
(* <<< TODO standardize this lemma *)
- cbn. rewrite (kbindd_comp_mret_eq).
compare naturals n and (countk k w); cbn; simpl_local.
+ rewrite monoid_id_r. compare naturals n and (countk k w).
+ rewrite monoid_id_r. cbn. compare naturals (countk k w) and (countk k w).
+ rewrite monoid_id_r. cbn. compare naturals n and (countk k w).
Qed.
Theorem subst_open_eq : ∀ k u1 u2 t x,
LC (T k) k u2 →
t '(k | u1) '{k | x ~> u2} =
t '{k | x ~> u2} '(k | u1 '{k | x ~> u2}).
Proof.
introv lc. compose near t.
unfold open, subst at 1 3.
rewrite (kbind_kbindd U), (kbindd_kbind U).
fequal. apply subst_open_eq_loc; auto.
Qed.
Theorem subst_open_neq_loc : ∀ k1 k2 (u1 : T k1 LN) (u2 : T k2 LN) (x : atom),
k1 ≠ k2 →
LC (T k2) k1 u2 →
(btgd k2 (subst_loc k2 x u2 ∘ extract (W := prod (list K)))) ⋆dm btgd k1 (open_loc k1 u1) =
(btgd k1 (open_loc k1 (mbind (T k1) (btg k2 (subst_loc k2 x u2)) u1))) ⋆dm (btg k2 (subst_loc k2 x u2) ◻ const (extract (W := prod (list K)))).
Proof.
introv Hneq HLC. ext j [w l].
unfold compose_dm.
compare values j and k1.
{ (* j = k1 *)
rewrite btgd_eq.
replace ((btg k2 (subst_loc k2 x u2) ◻ const extract) k1 (w, l))
with (btg k2 (subst_loc k2 x u2) k1 l) by (compare values k1 and k1).
rewrite btg_neq; auto.
compose near l on right.
rewrite mbindd_comp_mret.
unfold vec_compose at 2.
unfold allK at 2, const.
unfold compose at 2 3.
rewrite btgd_eq.
replace (incr w (ret l)) with (w, l).
2:{ cbn; now simpl_monoid. }
cbn. destruct l.
- compose near (Fr n) on left;
rewrite mbindd_comp_mret;
unfold compose; cbn;
compare values k1 and k2.
- compare naturals n and (countk k1 w).
+ compose near (Bd n) on left.
rewrite mbindd_comp_mret;
unfold compose; cbn;
compare values k1 and k2.
+ unfold mbind; fequal.
unfold vec_compose, allK, const.
ext j.
destruct_eq_args j k2.
× rewrite btg_eq, btgd_eq.
reassociate →.
replace (extract ∘ incr w) with (extract (W := prod (list K)) (A := LN)).
reflexivity.
symmetry; apply (extract_incr (A := LN) w).
× rewrite btgd_neq; auto.
rewrite btg_neq; auto.
reassociate →.
replace (extract ∘ incr w) with (extract (W := prod (list K)) (A := LN)).
reflexivity.
symmetry; apply (extract_incr (A := LN) w).
+ compose near (Bd (n - 1)) on left.
rewrite mbindd_comp_mret;
unfold compose; cbn;
compare values k1 and k2.
}
{ (* j <> k1 *)
rewrite btgd_neq; auto.
unfold vec_compose, const, compose.
cbn. compose near l on left.
rewrite mbindd_comp_mret.
compare values j and k2.
{ (* j = k2 *)
rewrite btgd_eq.
rewrite btg_eq.
unfold compose, allK, const. cbn.
compare l to atom x.
- (* l = Fr x *)
cbn. destruct_eq_args x x.
symmetry.
apply mbindd_respectful_id.
intros w' k l Hin.
compare values k and k1.
+ (* k = k1 *)
unfold LC, LCn in HLC.
specialize (HLC _ _ Hin).
unfold lc_loc in HLC.
destruct l.
{ cbn. compare values k1 and k1.
now destruct DESTR_EQ0.
}
{ rewrite btgd_eq.
cbn. unfold_ops @Monoid_op_list.
rewrite countk_app.
compare naturals n and (countk k1 w + countk k1 w'). }
+ (* k <> k1 *)
rewrite btgd_neq; auto.
- rewrite subst_loc_fr_neq.
compose near (Fr a) on right.
rewrite mbindd_comp_mret.
rewrite btgd_neq; auto.
inversion 1. congruence.
- cbn. compose near (Bd n) on right.
rewrite mbindd_comp_mret.
rewrite btgd_neq; auto.
}
{ (* j <> k2 *)
rewrite btgd_neq; auto.
rewrite btg_neq; auto.
compose near l on right.
rewrite (mbindd_comp_mret).
rewrite btgd_neq; auto. }
}
Qed.
Theorem subst_open_neq : ∀ k1 k2 (u1 : T k1 LN) (u2 : T k2 LN) (x : atom) (t : U LN),
k1 ≠ k2 →
LC (T k2) k1 u2 →
t '(k1 | u1) '{k2 | x ~> u2} =
t '{k2 | x ~> u2} '(k1 | u1 '{k2 | x ~> u2}).
Proof.
introv neq lc. compose near t.
unfold subst, open.
unfold kbind, kbindd.
rewrite (mbind_to_mbindd U), (mbindd_mbindd U).
rewrite (mbindd_mbindd U).
fequal.
pose (lemma := subst_open_neq_loc).
unfold compose_dm in lemma. setoid_rewrite <- lemma; auto.
ext k [w a]. unfold vec_compose.
fequal. ext j [w' a']. compare values j and k2.
+ rewrite btgd_eq, btg_eq. cbn. reflexivity.
+ rewrite btgd_neq, btg_neq; auto.
Qed.
Lemma open_spec_eq_loc : ∀ k u x w l,
l ≠ Fr x →
(subst (T k) k x u ∘ open_loc k (mret T k (Fr x))) (w, l) =
open_loc k u (w, l).
Proof.
introv neq. unfold compose. compare l to atom x.
- contradiction.
- cbn. rewrite subst_in_mret_eq, subst_loc_fr_neq.
trivial. intuition.
- cbn. compare naturals n and (countk k w).
now rewrite subst_in_mret_eq.
now rewrite subst_in_mret_eq, subst_loc_eq.
now rewrite subst_in_mret_eq, subst_loc_b.
Qed.
(* This theorem would be easy to prove with subst_open_eq, but
applying that theorem would introduce a local closure hypothesis
for <<u>> that is not actually required for our purposes. *)
Theorem open_spec_eq : ∀ k u t x,
¬ x `in` FV U k t →
t '(k | u) = t '(k | mret T k (Fr x)) '{k | x ~> u}.
Proof.
introv fresh. compose near t on right.
unfold subst, open. rewrite (kbind_kbindd U).
apply (kbindd_respectful). introv Hin.
assert (a ≠ Fr x).
{ apply (inmd_implies_in U) in Hin.
rewrite <- free_iff_FV in fresh.
eapply ninf_in_neq in fresh; eauto. }
now rewrite <- (open_spec_eq_loc k u x).
Qed.
l ≠ Fr x →
(subst (T k) k x u ∘ open_loc k (mret T k (Fr x))) (w, l) =
open_loc k u (w, l).
Proof.
introv neq. unfold compose. compare l to atom x.
- contradiction.
- cbn. rewrite subst_in_mret_eq, subst_loc_fr_neq.
trivial. intuition.
- cbn. compare naturals n and (countk k w).
now rewrite subst_in_mret_eq.
now rewrite subst_in_mret_eq, subst_loc_eq.
now rewrite subst_in_mret_eq, subst_loc_b.
Qed.
(* This theorem would be easy to prove with subst_open_eq, but
applying that theorem would introduce a local closure hypothesis
for <<u>> that is not actually required for our purposes. *)
Theorem open_spec_eq : ∀ k u t x,
¬ x `in` FV U k t →
t '(k | u) = t '(k | mret T k (Fr x)) '{k | x ~> u}.
Proof.
introv fresh. compose near t on right.
unfold subst, open. rewrite (kbind_kbindd U).
apply (kbindd_respectful). introv Hin.
assert (a ≠ Fr x).
{ apply (inmd_implies_in U) in Hin.
rewrite <- free_iff_FV in fresh.
eapply ninf_in_neq in fresh; eauto. }
now rewrite <- (open_spec_eq_loc k u x).
Qed.
Lemma subst_open_var_loc : ∀ k u x y,
x ≠ y →
LC (T k) k u →
subst (T k) k x u ∘ open_loc k (mret T k (Fr y)) =
open_loc k (mret T k (Fr y)) ⋆kdm (subst_loc k x u ∘ extract (W := prod (list K))).
Proof with auto.
introv neq lc. rewrite subst_open_eq_loc...
simpl_local. reflexivity.
Qed.
Theorem subst_open_var : ∀ k u t x y,
x ≠ y →
LC (T k) k u →
t '(k | mret T k (Fr y)) '{k | x ~> u} =
t '{k | x ~> u} '(k | mret T k (Fr y)).
Proof.
introv neq lc. compose near t.
unfold open, subst.
rewrite (kbind_kbindd U), (kbindd_kbind U).
fequal. apply subst_open_var_loc; auto.
Qed.
x ≠ y →
LC (T k) k u →
subst (T k) k x u ∘ open_loc k (mret T k (Fr y)) =
open_loc k (mret T k (Fr y)) ⋆kdm (subst_loc k x u ∘ extract (W := prod (list K))).
Proof with auto.
introv neq lc. rewrite subst_open_eq_loc...
simpl_local. reflexivity.
Qed.
Theorem subst_open_var : ∀ k u t x y,
x ≠ y →
LC (T k) k u →
t '(k | mret T k (Fr y)) '{k | x ~> u} =
t '{k | x ~> u} '(k | mret T k (Fr y)).
Proof.
introv neq lc. compose near t.
unfold open, subst.
rewrite (kbind_kbindd U), (kbindd_kbind U).
fequal. apply subst_open_var_loc; auto.
Qed.
Lemma open_close_loc : ∀ k x w l,
(open_loc k (mret T k (Fr x)) ∘ cobind (W := prod (list K))
(close_loc k x)) (w, l) = mret T k l.
Proof.
intros. cbn. unfold id. compare l to atom x.
- compare values x and x. compare naturals (countk k w) and (countk k w).
- compare values x and a.
- compare naturals n and (countk k w).
compare naturals (Datatypes.S (countk k w)) and (countk k w).
compare naturals (Datatypes.S n) and (countk k w).
Qed.
Theorem open_close : ∀ k x t,
('[k | x] t) '(k | mret T k (Fr x)) = t.
Proof.
intros. compose near t on left.
unfold open, close.
rewrite (kbindd_kmapd U).
apply (kbindd_respectful_id); intros.
apply open_close_loc.
Qed.
(open_loc k (mret T k (Fr x)) ∘ cobind (W := prod (list K))
(close_loc k x)) (w, l) = mret T k l.
Proof.
intros. cbn. unfold id. compare l to atom x.
- compare values x and x. compare naturals (countk k w) and (countk k w).
- compare values x and a.
- compare naturals n and (countk k w).
compare naturals (Datatypes.S (countk k w)) and (countk k w).
compare naturals (Datatypes.S n) and (countk k w).
Qed.
Theorem open_close : ∀ k x t,
('[k | x] t) '(k | mret T k (Fr x)) = t.
Proof.
intros. compose near t on left.
unfold open, close.
rewrite (kbindd_kmapd U).
apply (kbindd_respectful_id); intros.
apply open_close_loc.
Qed.
Opening by a LN reduces to an kmapd
Definition open_LN_loc k (u : LN) : list K × LN → LN :=
fun wl ⇒
match wl with
| (w, l) ⇒
match l with
| Fr x ⇒ Fr x
| Bd n ⇒
match Nat.compare n (countk k w) with
| Gt ⇒ Bd (n - 1)
| Eq ⇒ u
| Lt ⇒ Bd n
end
end
end.
Lemma open_by_LN_spec : ∀ k l,
open U k (mret T k l) = kmapd U k (open_LN_loc k l).
Proof.
intros. unfold open. ext t.
apply (kbindd_respectful_kmapd).
intros w l' l'in. destruct l'.
- reflexivity.
- cbn. compare naturals n and (countk k w).
Qed.
fun wl ⇒
match wl with
| (w, l) ⇒
match l with
| Fr x ⇒ Fr x
| Bd n ⇒
match Nat.compare n (countk k w) with
| Gt ⇒ Bd (n - 1)
| Eq ⇒ u
| Lt ⇒ Bd n
end
end
end.
Lemma open_by_LN_spec : ∀ k l,
open U k (mret T k l) = kmapd U k (open_LN_loc k l).
Proof.
intros. unfold open. ext t.
apply (kbindd_respectful_kmapd).
intros w l' l'in. destruct l'.
- reflexivity.
- cbn. compare naturals n and (countk k w).
Qed.
Lemma close_open_local : ∀ k x w l,
l ≠ Fr x →
(close_loc k x ∘ cobind (W := prod (list K))
(open_LN_loc k (Fr x))) (w, l) = l.
Proof.
introv neq. cbn. unfold id. compare l to atom x.
- contradiction.
- unfold compose; cbn. now compare values x and a.
- unfold compose; cbn.
compare naturals n and (countk k w). compare values x and x.
compare naturals (n - 1) and (countk k w).
Qed.
Theorem close_open : ∀ k x t,
¬ x ∈ free U k t →
'[k | x] (t '(k | mret T k (Fr x))) = t.
Proof.
introv fresh. compose near t on left.
rewrite open_by_LN_spec. unfold close.
rewrite (kmapd_kmapd U).
apply (kmapd_respectful_id).
intros w l lin.
assert (l ≠ Fr x).
{ rewrite neq_symmetry. apply (inmd_implies_in) in lin.
eapply (ninf_in_neq U). eassumption. auto. }
now apply close_open_local.
Qed.
l ≠ Fr x →
(close_loc k x ∘ cobind (W := prod (list K))
(open_LN_loc k (Fr x))) (w, l) = l.
Proof.
introv neq. cbn. unfold id. compare l to atom x.
- contradiction.
- unfold compose; cbn. now compare values x and a.
- unfold compose; cbn.
compare naturals n and (countk k w). compare values x and x.
compare naturals (n - 1) and (countk k w).
Qed.
Theorem close_open : ∀ k x t,
¬ x ∈ free U k t →
'[k | x] (t '(k | mret T k (Fr x))) = t.
Proof.
introv fresh. compose near t on left.
rewrite open_by_LN_spec. unfold close.
rewrite (kmapd_kmapd U).
apply (kmapd_respectful_id).
intros w l lin.
assert (l ≠ Fr x).
{ rewrite neq_symmetry. apply (inmd_implies_in) in lin.
eapply (ninf_in_neq U). eassumption. auto. }
now apply close_open_local.
Qed.
Lemma open_lc_gap_eq_1 : ∀ k n t u,
LC (T k) k u →
LCn U k n t →
LCn U k (n - 1) (t '(k | u)).
Proof.
unfold LCn.
introv lcu lct Hin. rewrite (inmd_open_iff_eq U) in Hin.
destruct Hin as [w1 [w2 [l1 [h1 [h2 h3]]]]].
destruct l1.
- cbn in h2. rewrite inmd_mret_eq_iff in h2.
destruct h2; subst. cbn. trivial.
- specialize (lct _ _ h1). cbn in h2. compare naturals n0 and (countk k w1).
+ rewrite inmd_mret_eq_iff in h2; destruct h2; subst.
cbn. unfold_monoid. List.simpl_list. lia.
+ specialize (lcu w2 l h2). unfold lc_loc in ×.
destruct l; [trivial|]. unfold_monoid. rewrite countk_app. lia.
+ rewrite inmd_mret_eq_iff in h2. destruct h2; subst.
unfold lc_loc in ×. unfold_monoid. List.simpl_list. lia.
Qed.
Lemma open_lc_gap_eq_2 : ∀ k n t u,
n > 0 →
LC (T k) k u →
LCn U k (n - 1) (t '(k | u)) →
LCn U k n t.
Proof.
unfold LCn.
introv ngt lcu lct Hin. setoid_rewrite (inmd_open_iff_eq U) in lct.
destruct l.
- cbv. trivial.
- compare naturals n0 and (countk k w).
+ specialize (lct w (Bd n0)).
lapply lct.
{ cbn; unfold_monoid; lia. }
{ ∃ w. ∃ (Ƶ : list K). ∃ (Bd n0).
split; auto. cbn. compare naturals n0 and (countk k w).
rewrite inmd_mret_eq_iff. now simpl_monoid. }
+ cbn. unfold_monoid; lia.
+ cbn. specialize (lct w (Bd (n0 - 1))).
lapply lct.
{ cbn; unfold_monoid; lia. }
{ ∃ w. ∃ (Ƶ : list K). ∃ (Bd n0).
split; auto. cbn. compare naturals n0 and (countk k w).
rewrite inmd_mret_eq_iff. now simpl_monoid. }
Qed.
Theorem open_lc_gap_eq_iff : ∀ k n t u,
n > 0 →
LC (T k) k u →
LCn U k n t ↔
LCn U k (n - 1) (t '(k | u)).
Proof.
intros; intuition (eauto using open_lc_gap_eq_1, open_lc_gap_eq_2).
Qed.
Corollary open_lc_gap_eq_var : ∀ k n t x,
n > 0 →
LCn U k n t ↔
LCn U k (n - 1) (t '(k | mret T k (Fr x))).
Proof.
intros. apply open_lc_gap_eq_iff. auto.
intros w l hin. rewrite inmd_mret_eq_iff in hin.
destruct hin; subst. cbv. trivial.
Qed.
Corollary open_lc_gap_eq_iff_1 : ∀ k t u,
LC (T k) k u →
LCn U k 1 t ↔
LC U k (t '(k | u)).
Proof.
intros. unfold LC.
change 0 with (1 - 1).
rewrite <- open_lc_gap_eq_iff; auto.
reflexivity.
Qed.
Corollary open_lc_gap_eq_var_1 : ∀ k t x,
LCn U k 1 t ↔
LC U k (t '(k | mret T k (Fr x))).
Proof.
intros. unfold LC.
change 0 with (1 - 1).
rewrite <- open_lc_gap_eq_var; auto.
reflexivity.
Qed.
Lemma open_lc_gap_neq_1 : ∀ k j n t u,
k ≠ j →
LC (T j) k u →
LCn U k n t →
LCn U k n (t '(j | u)).
Proof.
unfold LCn.
introv neq lcu lct Hin.
rewrite (inmd_open_neq_iff U) in Hin; auto.
destruct Hin as [Hin | Hin].
- auto.
- destruct Hin as [w1 [w2 [l1 [in_t [in_open ?]]]]].
subst. destruct l1.
+ cbn in in_open. rewrite inmd_mret_iff in in_open.
exfalso. intuition.
+ destruct l.
{ cbn. trivial. }
{ cbn. cbn in in_open.
compare naturals n0 and (countk j w1).
- rewrite inmd_mret_iff in in_open. exfalso; intuition.
- specialize (lcu _ _ in_open).
unfold lc_loc in lcu. unfold_monoid.
rewrite countk_app. lia.
- rewrite inmd_mret_iff in in_open. exfalso; intuition.
}
Qed.
Lemma open_lc_gap_neq_2 : ∀ k j n t u,
k ≠ j →
LC (T j) k u →
LCn U k n (t '(j | u)) →
LCn U k n t.
Proof.
unfold LCn.
introv neq lcu lct Hin.
destruct l.
+ cbn. auto.
+ specialize (lct w (Bd n0)).
apply lct. rewrite (inmd_open_neq_iff U); auto.
Qed.
Theorem open_lc_gap_neq_iff : ∀ k j n t u,
k ≠ j →
LC (T j) k u →
LCn U k n t ↔
LCn U k n (t '(j | u)).
Proof.
intros. intuition (eauto using open_lc_gap_neq_1, open_lc_gap_neq_2).
Qed.
Corollary open_lc_gap_neq_var : ∀ k j t x,
k ≠ j →
LC U k t ↔
LC U k (t '(j | mret T j (Fr x))).
Proof.
intros. unfold LC.
rewrite open_lc_gap_neq_iff; eauto.
reflexivity. unfold LC, LCn.
setoid_rewrite inmd_mret_iff. intuition.
Qed.
End open_metatheory.
LC (T k) k u →
LCn U k n t →
LCn U k (n - 1) (t '(k | u)).
Proof.
unfold LCn.
introv lcu lct Hin. rewrite (inmd_open_iff_eq U) in Hin.
destruct Hin as [w1 [w2 [l1 [h1 [h2 h3]]]]].
destruct l1.
- cbn in h2. rewrite inmd_mret_eq_iff in h2.
destruct h2; subst. cbn. trivial.
- specialize (lct _ _ h1). cbn in h2. compare naturals n0 and (countk k w1).
+ rewrite inmd_mret_eq_iff in h2; destruct h2; subst.
cbn. unfold_monoid. List.simpl_list. lia.
+ specialize (lcu w2 l h2). unfold lc_loc in ×.
destruct l; [trivial|]. unfold_monoid. rewrite countk_app. lia.
+ rewrite inmd_mret_eq_iff in h2. destruct h2; subst.
unfold lc_loc in ×. unfold_monoid. List.simpl_list. lia.
Qed.
Lemma open_lc_gap_eq_2 : ∀ k n t u,
n > 0 →
LC (T k) k u →
LCn U k (n - 1) (t '(k | u)) →
LCn U k n t.
Proof.
unfold LCn.
introv ngt lcu lct Hin. setoid_rewrite (inmd_open_iff_eq U) in lct.
destruct l.
- cbv. trivial.
- compare naturals n0 and (countk k w).
+ specialize (lct w (Bd n0)).
lapply lct.
{ cbn; unfold_monoid; lia. }
{ ∃ w. ∃ (Ƶ : list K). ∃ (Bd n0).
split; auto. cbn. compare naturals n0 and (countk k w).
rewrite inmd_mret_eq_iff. now simpl_monoid. }
+ cbn. unfold_monoid; lia.
+ cbn. specialize (lct w (Bd (n0 - 1))).
lapply lct.
{ cbn; unfold_monoid; lia. }
{ ∃ w. ∃ (Ƶ : list K). ∃ (Bd n0).
split; auto. cbn. compare naturals n0 and (countk k w).
rewrite inmd_mret_eq_iff. now simpl_monoid. }
Qed.
Theorem open_lc_gap_eq_iff : ∀ k n t u,
n > 0 →
LC (T k) k u →
LCn U k n t ↔
LCn U k (n - 1) (t '(k | u)).
Proof.
intros; intuition (eauto using open_lc_gap_eq_1, open_lc_gap_eq_2).
Qed.
Corollary open_lc_gap_eq_var : ∀ k n t x,
n > 0 →
LCn U k n t ↔
LCn U k (n - 1) (t '(k | mret T k (Fr x))).
Proof.
intros. apply open_lc_gap_eq_iff. auto.
intros w l hin. rewrite inmd_mret_eq_iff in hin.
destruct hin; subst. cbv. trivial.
Qed.
Corollary open_lc_gap_eq_iff_1 : ∀ k t u,
LC (T k) k u →
LCn U k 1 t ↔
LC U k (t '(k | u)).
Proof.
intros. unfold LC.
change 0 with (1 - 1).
rewrite <- open_lc_gap_eq_iff; auto.
reflexivity.
Qed.
Corollary open_lc_gap_eq_var_1 : ∀ k t x,
LCn U k 1 t ↔
LC U k (t '(k | mret T k (Fr x))).
Proof.
intros. unfold LC.
change 0 with (1 - 1).
rewrite <- open_lc_gap_eq_var; auto.
reflexivity.
Qed.
Lemma open_lc_gap_neq_1 : ∀ k j n t u,
k ≠ j →
LC (T j) k u →
LCn U k n t →
LCn U k n (t '(j | u)).
Proof.
unfold LCn.
introv neq lcu lct Hin.
rewrite (inmd_open_neq_iff U) in Hin; auto.
destruct Hin as [Hin | Hin].
- auto.
- destruct Hin as [w1 [w2 [l1 [in_t [in_open ?]]]]].
subst. destruct l1.
+ cbn in in_open. rewrite inmd_mret_iff in in_open.
exfalso. intuition.
+ destruct l.
{ cbn. trivial. }
{ cbn. cbn in in_open.
compare naturals n0 and (countk j w1).
- rewrite inmd_mret_iff in in_open. exfalso; intuition.
- specialize (lcu _ _ in_open).
unfold lc_loc in lcu. unfold_monoid.
rewrite countk_app. lia.
- rewrite inmd_mret_iff in in_open. exfalso; intuition.
}
Qed.
Lemma open_lc_gap_neq_2 : ∀ k j n t u,
k ≠ j →
LC (T j) k u →
LCn U k n (t '(j | u)) →
LCn U k n t.
Proof.
unfold LCn.
introv neq lcu lct Hin.
destruct l.
+ cbn. auto.
+ specialize (lct w (Bd n0)).
apply lct. rewrite (inmd_open_neq_iff U); auto.
Qed.
Theorem open_lc_gap_neq_iff : ∀ k j n t u,
k ≠ j →
LC (T j) k u →
LCn U k n t ↔
LCn U k n (t '(j | u)).
Proof.
intros. intuition (eauto using open_lc_gap_neq_1, open_lc_gap_neq_2).
Qed.
Corollary open_lc_gap_neq_var : ∀ k j t x,
k ≠ j →
LC U k t ↔
LC U k (t '(j | mret T j (Fr x))).
Proof.
intros. unfold LC.
rewrite open_lc_gap_neq_iff; eauto.
reflexivity. unfold LC, LCn.
setoid_rewrite inmd_mret_iff. intuition.
Qed.
End open_metatheory.