Built with Alectryon, running Coq+SerAPI v8.16.0+0.16.3. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
From Tealeaves Require Export
Examples.STLC.Syntax.Import Syntax.TermNotations.#[local] Open Scope set_scope.Implicit Types (x: atom) (τ: typ)
(tu: term) (n: nat) (v: LN) (Γ: ctx).Ltacgather_atoms ::=
letA := gather_atoms_with (funs: AtomSet.t => s) inletB := gather_atoms_with (funx: atom => {{ x }}) inletC := gather_atoms_with (funt: term => FV t) inletD := gather_atoms_with (funΓ: alist typ => domset Γ) inconstr:(A ∪ B ∪ C ∪ D).(** * Inversion lemmas *)(**********************************************************************)
forallτxΓ, Γ ⊢ tvar x : τ -> (x, τ) ∈ Γ
forallτxΓ, Γ ⊢ tvar x : τ -> (x, τ) ∈ Γ
inversion1; auto.Qed.
forallτnΓ, Γ ⊢ tvar n : τ -> False
forallτnΓ, Γ ⊢ tvar n : τ -> False
inversion1; auto.Qed.(* This is somewhat weak because L should really be (dom Γ) *)
forall (τB : typ) (e : term) Γ,
Γ ⊢ (λ) τ e : B ->
existsC : typ,
B = τ ⟹ C /\
(existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ e '(x) : C)
forall (τB : typ) (e : term) Γ,
Γ ⊢ (λ) τ e : B ->
existsC : typ,
B = τ ⟹ C /\
(existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ e '(x) : C)
τ, B: typ e: term Γ: ctx J: Γ ⊢ (λ) τ e : B
existsC : typ,
B = τ ⟹ C /\
(existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : C)
τ: typ e: term Γ: ctx τ2: typ J: Γ ⊢ (λ) τ e : τ ⟹ τ2 L: AtomSet.t H3: forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : τ2
existsC : typ,
τ ⟹ τ2 = τ ⟹ C /\
(existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : C)
τ: typ e: term Γ: ctx τ2: typ J: Γ ⊢ (λ) τ e : τ ⟹ τ2 L: AtomSet.t H3: forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : τ2
τ ⟹ τ2 = τ ⟹ τ2 /\
(existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ open x e : τ2)
split; auto; existsL; auto.Qed.(** Inversion principle for [abs] where we may assume the abstraction has arrow type *)
forallττ' (e : term) Γ,
Γ ⊢ (λ) τ e : τ ⟹ τ' ->
existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ e '(x : term) : τ'
forallττ' (e : term) Γ,
Γ ⊢ (λ) τ e : τ ⟹ τ' ->
existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ e '(x : term) : τ'
τ, τ': typ e: term Γ: ctx J: Γ ⊢ (λ) τ e : τ ⟹ τ'
existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ open x e : τ'
τ, τ': typ e: term Γ: ctx J: existsC : typ,
τ ⟹ τ' = τ ⟹ C /\
(existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : C)
existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ open x e : τ'
τ, τ': typ e: term Γ: ctx C: typ H1: τ ⟹ τ' = τ ⟹ C H2: existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : C
existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ open x e : τ'
τ: typ e: term Γ: ctx C: typ H1: τ ⟹ C = τ ⟹ C H2: existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x e : C
existsL : AtomSet.t,
forallx, x `notin` L -> Γ ++ x ~ τ ⊢ open x e : C
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
uniq Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx, x `notin` L -> uniq (Γ ++ x ~ τ1)
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
uniq Γ
assumption.
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx, x `notin` L -> uniq (Γ ++ x ~ τ1)
uniq Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: uniq (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ))
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
FV x ⊆ domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx,
x `notin` L ->
FV (open x body) ⊆ domset (Γ ++ x ~ τ1)
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
FV x ⊆ domset Γ
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
{{x}} ⊆ domset Γ
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: x `in` domset Γ
{{x}} ⊆ domset Γ
fsetdec.
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx,
x `notin` L ->
FV (open x body) ⊆ domset (Γ ++ x ~ τ1)
FV ((λ) τ1 body) ⊆ domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ))
FV ((λ) τ1 body) ⊆ domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ))
FV body ⊆ domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term))
FV body ⊆ domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term)) step2: forallx,
x `in` FV body -> x `in` domset (Γ ++ e ~ τ1)
FV body ⊆ domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term)) step2: forallx,
x `in` FV body -> x `in` domset (Γ ++ e ~ τ1) x: AtomSet.elt xin: x `in` FV body
x `in` domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term)) step2: forallx,
x `in` FV body -> x `in` domset (Γ ++ e ~ τ1) x: AtomSet.elt xin: x `in` FV body H: x <> e
x `in` domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term)) x: AtomSet.elt step2: x `in` domset (Γ ++ e ~ τ1) xin: x `in` FV body H: x <> e
x `in` domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term)) x: AtomSet.elt step2: x `in` (domset Γ ∪ domset (e ~ τ1)) xin: x `in` FV body H: x <> e
x `in` domset Γ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 e: atom IHbody: FV (open e body) ⊆ domset (Γ ++ e ~ τ1) Hfresh: e `notin` (L ∪ (FV body ∪ domset Γ)) step1: FV body ⊆ FV (body '(e : term)) x: AtomSet.elt step2: x `in` (domset Γ ∪ {{e}}) xin: x `in` FV body H: x <> e
forall (L : AtomSet.t) t (X : typ),
(forallx, x `notin` L -> LC (t '(x : term))) ->
LC ((λ) X t)
forall (L : AtomSet.t) t (X : typ),
(forallx, x `notin` L -> LC (t '(x : term))) ->
LC ((λ) X t)
L: AtomSet.t t: term X: typ HLC: forallx, x `notin` L -> LC (open x t)
LC ((λ) X t)
L: AtomSet.t t: term X: typ HLC: forallx, x `notin` L -> LC (open x t)
LCn 1 t
L: AtomSet.t t: term X: typ e: atom HLC: LC (open e t) Hfresh: e `notin` (L ∪ FV t)
LCn 1 t
L: AtomSet.t t: term X: typ e: atom HLC: LC (open (ret e) t) Hfresh: e `notin` (L ∪ FV t)
LCn 1 t
L: AtomSet.t t: term X: typ e: atom HLC: LCn 1 t Hfresh: e `notin` (L ∪ FV t)
LCn 1 t
assumption.Qed.
forallΓtτ, Γ ⊢ t : τ -> LC t
forallΓtτ, Γ ⊢ t : τ -> LC t
Γ: ctx t: term τ: typ J: Γ ⊢ t : τ
LC t
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
LC x
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx, x `notin` L -> LC (open x body)
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
LC x
Γ: ctx x: atom τ0: typ Huniq: uniq Γ Hin: (x, τ0) ∈ Γ
True
exact I.
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx, x `notin` L -> LC (open x body)
LC ((λ) τ1 body)
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx, x `notin` L -> LC (open x body) y: atom Fr: y `notin` L
forallΓ1Γ2Γ'tτ,
uniq Γ' ->
disjoint Γ' (Γ1 ++ Γ2) ->
Γ1 ++ Γ2 ⊢ t : τ -> Γ1 ++ Γ' ++ Γ2 ⊢ t : τ
forallΓ1Γ2Γ'tτ,
uniq Γ' ->
disjoint Γ' (Γ1 ++ Γ2) ->
Γ1 ++ Γ2 ⊢ t : τ -> Γ1 ++ Γ' ++ Γ2 ⊢ t : τ
Γ1, Γ2, Γ': ctx t: term τ: typ Huq: uniq Γ' Hdj: disjoint Γ' (Γ1 ++ Γ2) J: Γ1 ++ Γ2 ⊢ t : τ
Γ1 ++ Γ' ++ Γ2 ⊢ t : τ
Γ1, Γ2, Γ': ctx t: term τ: typ Huq: uniq Γ' Γrem: list (atom * typ) HeqΓrem: Γrem = Γ1 ++ Γ2 Hdj: disjoint Γ' Γrem J: Γrem ⊢ t : τ
Γ1 ++ Γ' ++ Γ2 ⊢ t : τ
Γ1, Γ': ctx t: term τ: typ Huq: uniq Γ' Γrem: list (atom * typ) Hdj: disjoint Γ' Γrem J: Γrem ⊢ t : τ
forallΓ2, Γrem = Γ1 ++ Γ2 -> Γ1 ++ Γ' ++ Γ2 ⊢ t : τ
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq (Γ1 ++ Γ2)
Γ1 ++ Γ' ++ Γ2 ⊢ x : τ0
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term IHbody: forallx,
x `notin` L ->
disjoint Γ' ((Γ1 ++ Γ2) ++ x ~ τ1) ->
forallΓ3,
(Γ1 ++ Γ2) ++ x ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open x body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq (Γ1 ++ Γ2)
Γ1 ++ Γ' ++ Γ2 ⊢ x : τ0
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq (Γ1 ++ Γ2)
uniq (Γ1 ++ Γ' ++ Γ2)
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq (Γ1 ++ Γ2)
(x, τ0) ∈ (Γ1 ++ Γ' ++ Γ2)
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq (Γ1 ++ Γ2)
uniq (Γ1 ++ Γ' ++ Γ2)
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ1 Γ' /\ disjoint Γ2 Γ' x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq Γ1 /\ uniq Γ2 /\ disjoint Γ1 Γ2
uniq Γ1 /\
(uniq Γ' /\ uniq Γ2 /\ disjoint Γ' Γ2) /\
disjoint Γ' Γ1 /\ disjoint Γ2 Γ1
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ1 Γ' /\ disjoint Γ2 Γ' x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq Γ1 /\ uniq Γ2 /\ disjoint Γ1 Γ2
uniq Γ1 /\
(uniq Γ' /\ uniq Γ2 /\ disjoint Γ2 Γ') /\
disjoint Γ' Γ1 /\ disjoint Γ2 Γ1
preprocess; intuition.
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ (Γ1 ++ Γ2) Huniq: uniq (Γ1 ++ Γ2)
(x, τ0) ∈ (Γ1 ++ Γ' ++ Γ2)
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) x: atom τ0: typ Hin: (x, τ0) ∈ Γ1 \/ (x, τ0) ∈ Γ2 Huniq: uniq (Γ1 ++ Γ2)
(x, τ0) ∈ Γ1 \/ (x, τ0) ∈ Γ' \/ (x, τ0) ∈ Γ2
intuition.
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term IHbody: forallx,
x `notin` L ->
disjoint Γ' ((Γ1 ++ Γ2) ++ x ~ τ1) ->
forallΓ3,
(Γ1 ++ Γ2) ++ x ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open x body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2
Γ1 ++ Γ' ++ Γ2 ⊢ (λ) τ1 body : τ1 ⟹ τ2
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term IHbody: forallx,
x `notin` L ->
disjoint Γ' ((Γ1 ++ Γ2) ++ x ~ τ1) ->
forallΓ3,
(Γ1 ++ Γ2) ++ x ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open x body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 y: atom Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
(Γ1 ++ Γ' ++ Γ2) ++ y ~ τ1 ⊢ open y body : τ2
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' ((Γ1 ++ Γ2) ++ y ~ τ1) ->
forallΓ3,
(Γ1 ++ Γ2) ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
(Γ1 ++ Γ' ++ Γ2) ++ y ~ τ1 ⊢ open y body : τ2
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
(Γ1 ++ Γ' ++ Γ2) ++ y ~ τ1 ⊢ open y body : τ2
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
Γ1 ++ Γ' ++ Γ2 ++ y ~ τ1 ⊢ open y body : τ2
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1)
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ2 ++ y ~ τ1
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1)
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ1 Γ' /\ disjoint Γ2 Γ' L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ1 Γ' /\
disjoint Γ2 Γ' /\ y `notin` domset Γ' ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
disjoint Γ1 Γ' /\
disjoint Γ2 Γ' /\ y `notin` domset Γ'
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ1 Γ' /\ disjoint Γ2 Γ' L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ1 Γ' /\
disjoint Γ2 Γ' /\ y `notin` domset Γ' ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
y `notin` domset Γ'
fsetdec.
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ2 ++ y ~ τ1
Γ1, Γ': ctx Huq: uniq Γ' Γ2: ctx Hdj: disjoint Γ' (Γ1 ++ Γ2) L: AtomSet.t τ1, τ2: typ body: term y: atom IHbody: disjoint Γ' (Γ1 ++ Γ2 ++ y ~ τ1) ->
forallΓ3,
Γ1 ++ Γ2 ++ y ~ τ1 = Γ1 ++ Γ3 ->
Γ1 ++ Γ' ++ Γ3 ⊢ open y body : τ2 Jbody: forallx,
x `notin` L ->
(Γ1 ++ Γ2) ++ x ~ τ1 ⊢ open x body : τ2 Fr: y
`notin` (L
∪ (FV body
∪ (domset Γ1
∪ (domset Γ' ∪ domset Γ2))))
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
Γ1 ++ Γ2 ⊢ subst x u x0 : τ
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
Γ1 ++ Γ2 ⊢ ret x0 : τ
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
uniq (Γ1 ++ Γ2)
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
(x0, τ) ∈ (Γ1 ++ Γ2)
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
uniq (Γ1 ++ Γ2)
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq Γ1 /\
(True /\ uniq Γ2 /\ x `notin` domset Γ2) /\
x `notin` domset Γ1 /\ disjoint Γ2 Γ1 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
uniq Γ1 /\ uniq Γ2 /\ disjoint Γ1 Γ2
intuition.
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
(x0, τ) ∈ (Γ1 ++ Γ2)
Γ1: ctx x: atom u: term τ1: typ x0: atom τ: typ Γ2: ctx Hin: (x0, τ) ∈ (Γ1 ++ x ~ τ1 ++ Γ2) Huniq: uniq (Γ1 ++ x ~ τ1 ++ Γ2) Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u DESTR_NEQ: x <> x0 DESTR_NEQs: x0 <> x
(x0, τ) ∈ (Γ1 ++ Γ2)
eauto using binds_remove_mid.}
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 IHbody: forallx0,
x0 `notin` L ->
(foralltτ,
Γ ++ x0 ~ τ0 ⊢ t : τ -> uniq (Γ ++ x0 ~ τ0)) ->
forallΓ2,
Γ ++ x0 ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open x0 body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2
Γ1 ++ Γ2 ⊢ subst x u ((λ) τ0 body) : τ0 ⟹ τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 IHbody: forallx0,
x0 `notin` L ->
(foralltτ,
Γ ++ x0 ~ τ0 ⊢ t : τ -> uniq (Γ ++ x0 ~ τ0)) ->
forallΓ2,
Γ ++ x0 ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open x0 body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2
Γ1 ++ Γ2 ⊢ (λ) τ0 (subst x u body) : τ0 ⟹ τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 IHbody: forallx0,
x0 `notin` L ->
(foralltτ,
Γ ++ x0 ~ τ0 ⊢ t : τ -> uniq (Γ ++ x0 ~ τ0)) ->
forallΓ2,
Γ ++ x0 ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open x0 body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2
forallx0,
x0 `notin` (L ∪ domset Γ ∪ {{x}}) ->
(Γ1 ++ Γ2) ++ x0 ~ τ0 ⊢ open x0 (subst x u body) : τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
(Γ1 ++ Γ2) ++ e ~ τ0 ⊢ open e (subst x u body) : τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
(Γ1 ++ Γ2) ++ e ~ τ0 ⊢ open (ret e) (subst x u body)
: τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
(Γ1 ++ Γ2) ++ e ~ τ0 ⊢ subst x u (open (ret e) body)
: τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
x <> e
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
LC u
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
(Γ1 ++ Γ2) ++ e ~ τ0 ⊢ subst x u (open (ret e) body)
: τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
Γ1 ++ Γ2 ++ e ~ τ0 ⊢ subst x u (open (ret e) body)
: τ3
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
foralltτ, Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ++ e ~ τ0
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
foralltτ, Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)
eauto using j_ctx_wf.
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ++ e ~ τ0
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t τ0, τ3: typ body: term Γ2: ctx Jbody: forallx0,
x0 `notin` L ->
(Γ1 ++ x ~ τ1 ++ Γ2) ++ x0 ~ τ0 ⊢
open x0 body : τ3 e: atom IHbody: (foralltτ,
(Γ1 ++ x ~ τ1 ++ Γ2) ++ e ~ τ0 ⊢ t : τ ->
uniq ((Γ1 ++ x ~ τ1 ++ Γ2) ++ e ~ τ0)) ->
forallΓ3,
(Γ1 ++ x ~ τ1 ++ Γ2) ++ e ~ τ0 =
Γ1 ++ x ~ τ1 ++ Γ3 ->
Γ1 ++ Γ3 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ,
Γ1 ++ x ~ τ1 ++ Γ2 ⊢ t : τ ->
uniq (Γ1 ++ x ~ τ1 ++ Γ2) H: LC u Notin: e
`notin` (L ∪ domset (Γ1 ++ x ~ τ1 ++ Γ2)
∪ {{x}})
(Γ1 ++ x ~ τ1 ++ Γ2) ++ e ~ τ0 =
Γ1 ++ x ~ τ1 ++ Γ2 ++ e ~ τ0
now simpl_alist.
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
x <> e
fsetdec.
Γ1: ctx x: atom u: term τ1: typ L: AtomSet.t Γ: ctx τ0, τ3: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ0 ⊢ open x body : τ3 e: atom IHbody: (foralltτ,
Γ ++ e ~ τ0 ⊢ t : τ -> uniq (Γ ++ e ~ τ0)) ->
forallΓ2,
Γ ++ e ~ τ0 = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u (open e body) : τ3 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2 Notin: e `notin` (L ∪ domset Γ ∪ {{x}})
LC u
auto.
Γ1: ctx x: atom u: term τ1: typ Γ: ctx t1, t2: term τ0, τ3: typ J1: Γ ⊢ t1 : τ0 ⟹ τ3 J2: Γ ⊢ t2 : τ0 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u IHJ1: (foralltτ, Γ ⊢ t : τ -> uniq Γ) ->
forallΓ2,
Γ = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u t1 : τ0 ⟹ τ3 IHJ2: (foralltτ, Γ ⊢ t : τ -> uniq Γ) ->
forallΓ2,
Γ = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u t2 : τ0 Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2
Γ1 ++ Γ2 ⊢ subst x u (⟨ t1 ⟩ (t2)) : τ3
Γ1: ctx x: atom u: term τ1: typ Γ: ctx t1, t2: term τ0, τ3: typ J1: Γ ⊢ t1 : τ0 ⟹ τ3 J2: Γ ⊢ t2 : τ0 Ju: Γ1 ⊢ u : τ1 Hwf: foralltτ, Γ ⊢ t : τ -> uniq Γ H: LC u IHJ1: (foralltτ, Γ ⊢ t : τ -> uniq Γ) ->
forallΓ2,
Γ = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u t1 : τ0 ⟹ τ3 IHJ2: (foralltτ, Γ ⊢ t : τ -> uniq Γ) ->
forallΓ2,
Γ = Γ1 ++ x ~ τ1 ++ Γ2 ->
Γ1 ++ Γ2 ⊢ subst x u t2 : τ0 Γ2: ctx HeqΓ: Γ = Γ1 ++ x ~ τ1 ++ Γ2
Γ1 ++ Γ2 ⊢ ⟨ subst x u t1 ⟩ (subst x u t2) : τ3
eauto using j_app.Qed.
forallΓxtu (AB : typ),
Γ ++ x ~ A ⊢ t : B ->
Γ ⊢ u : A -> Γ ⊢ t '{ x ~> u} : B
forallΓxtu (AB : typ),
Γ ++ x ~ A ⊢ t : B ->
Γ ⊢ u : A -> Γ ⊢ t '{ x ~> u} : B
Γ: ctx x: atom t, u: term A, B: typ Jt: Γ ++ x ~ A ⊢ t : B Ju: Γ ⊢ u : A
Γ ⊢ subst x u t : B
Γ: ctx x: atom t, u: term A, B: typ Jt: Γ ++ x ~ A ++ [] ⊢ t : B Ju: Γ ⊢ u : A
Γ ⊢ subst x u t : B
Γ: ctx x: atom t, u: term A, B: typ Jt: Γ ++ x ~ A ++ [] ⊢ t : B Ju: Γ ⊢ u : A
foralltt'Γ (A : typ),
Γ ⊢ t : A -> beta_step t t' -> Γ ⊢ t' : A
foralltt'Γ (A : typ),
Γ ⊢ t : A -> beta_step t t' -> Γ ⊢ t' : A
t, t': term Γ: ctx A: typ J: Γ ⊢ t : A Hstep: beta_step t t'
Γ ⊢ t' : A
t: term Γ: ctx A: typ J: Γ ⊢ t : A
forallt', beta_step t t' -> Γ ⊢ t' : A
Γ: ctx x: atom τ: typ Huniq: uniq Γ Hin: (x, τ) ∈ Γ t': term Hstep: beta_step x t'
Γ ⊢ t' : τ
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx,
x `notin` L ->
forallt',
beta_step (open x body) t' ->
Γ ++ x ~ τ1 ⊢ t' : τ2 t': term Hstep: beta_step ((λ) τ1 body) t'
Γ: ctx x: atom τ: typ Huniq: uniq Γ Hin: (x, τ) ∈ Γ t': term Hstep: beta_step x t'
Γ ⊢ t' : τ
inversion Hstep.
L: AtomSet.t Γ: ctx τ1, τ2: typ body: term Jbody: forallx,
x `notin` L -> Γ ++ x ~ τ1 ⊢ open x body : τ2 IHbody: forallx,
x `notin` L ->
forallt',
beta_step (open x body) t' ->
Γ ++ x ~ τ1 ⊢ t' : τ2 t': term Hstep: beta_step ((λ) τ1 body) t'
Γ: ctx t2: term τ1, τ2, τ: typ t: term J1: existsC : typ,
τ1 ⟹ τ2 = τ ⟹ C /\
(existsL : AtomSet.t,
forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x t : C) J2: Γ ⊢ t2 : τ1 IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ1 ⟹ τ2 IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ1 Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t)
Γ ⊢ open t2 t : τ2
Γ: ctx t2: term τ1, τ2, τ: typ t: term C: typ hyp1: τ1 ⟹ τ2 = τ ⟹ C L: AtomSet.t hyp2: forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x t : C J2: Γ ⊢ t2 : τ1 IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ1 ⟹ τ2 IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ1 Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t)
Γ ⊢ open t2 t : τ2
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t hyp2: forallx,
x `notin` L -> Γ ++ x ~ τ ⊢ open x t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t)
Γ ⊢ open t2 t : C
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t e: atom hyp2: Γ ++ e ~ τ ⊢ open e t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t) Hfresh: e `notin` (L ∪ (FV t2 ∪ (FV t ∪ domset Γ)))
Γ ⊢ open t2 t : C
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t e: atom hyp2: Γ ++ e ~ τ ⊢ open e t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t) Hfresh: e `notin` (L ∪ (FV t2 ∪ (FV t ∪ domset Γ)))
Γ ⊢ subst e t2 (open (ret e) t) : C
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t e: atom hyp2: Γ ++ e ~ τ ⊢ open e t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t) Hfresh: e `notin` (L ∪ (FV t2 ∪ (FV t ∪ domset Γ)))
e `notin` FV t
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t e: atom hyp2: Γ ++ e ~ τ ⊢ open e t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t) Hfresh: e `notin` (L ∪ (FV t2 ∪ (FV t ∪ domset Γ)))
Γ ⊢ subst e t2 (open (ret e) t) : C
eauto using substitution_r.
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t e: atom hyp2: Γ ++ e ~ τ ⊢ open e t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t) Hfresh: e `notin` (L ∪ (FV t2 ∪ (FV t ∪ domset Γ)))
e `notin` FV t
Γ: ctx t2: term τ: typ t: term C: typ hyp1: τ ⟹ C = τ ⟹ C L: AtomSet.t e: atom hyp2: Γ ++ e ~ τ ⊢ open e t : C IHJ2: forallt', beta_step t2 t' -> Γ ⊢ t' : τ IHJ1: forallt',
beta_step ((λ) τ t) t' -> Γ ⊢ t' : τ ⟹ C J2: Γ ⊢ t2 : τ Hstep: beta_step (⟨ (λ) τ t ⟩ (t2)) (open t2 t) Hfresh: e `notin` (L ∪ (FV t2 ∪ (FV t ∪ domset Γ)))
e `notin` FV t
fsetdec.}Qed.
foralltτ1,
[] ⊢ t : τ1 -> value t \/ (existst', beta_step t t')
foralltτ1,
[] ⊢ t : τ1 -> value t \/ (existst', beta_step t t')
t: term τ1: typ J: [] ⊢ t : τ1
value t \/ (existst', beta_step t t')
t: term τ1: typ ctx: list (atom * typ) Heqctx: ctx = [] J: ctx ⊢ t : τ1
value t \/ (existst', beta_step t t')
x: atom τ: typ Hin: (x, τ) ∈ [] Huniq: uniq []
value x \/ (existst', beta_step x t')
L: AtomSet.t τ0, τ2: typ body: term IHbody: forallx,
x `notin` L ->
[] ++ x ~ τ0 = [] ->
value (open x body) \/
(existst', beta_step (open x body) t') Jbody: forallx,
x `notin` L -> [] ++ x ~ τ0 ⊢ open x body : τ2
L: AtomSet.t τ0, τ2: typ body: term IHbody: forallx,
x `notin` L ->
[] ++ x ~ τ0 = [] ->
value (open x body) \/
(existst', beta_step (open x body) t') Jbody: forallx,
x `notin` L -> [] ++ x ~ τ0 ⊢ open x body : τ2
L: AtomSet.t τ0, τ2: typ body: term IHbody: forallx,
x `notin` L ->
[] ++ x ~ τ0 = [] ->
value (open x body) \/
(existst', beta_step (open x body) t') Jbody: forallx,
x `notin` L -> [] ++ x ~ τ0 ⊢ open x body : τ2
t1, t2: term τ0, τ2: typ IHJ2: value t2 \/ (existst', beta_step t2 t') t1': term Hstep': beta_step t1 t1' J2: [] ⊢ t2 : τ0 J1: [] ⊢ t1 : τ0 ⟹ τ2
existst', beta_step (⟨ t1 ⟩ (t2)) t'
eauto using beta_app_l.Qed.
foralltτ1,
[] ⊢ t : τ1 -> value t \/ (existst', beta_step t t')
foralltτ1,
[] ⊢ t : τ1 -> value t \/ (existst', beta_step t t')
t: term τ1: typ J: [] ⊢ t : τ1
value t \/ (existst', beta_step t t')
t: term τ1: typ ctx: list (atom * typ) Heqctx: ctx = [] J: ctx ⊢ t : τ1
value t \/ (existst', beta_step t t')
x: atom τ: typ Hin: (x, τ) ∈ [] Huniq: uniq []
value x \/ (existst', beta_step x t')
L: AtomSet.t τ0, τ2: typ body: term IHbody: forallx,
x `notin` L ->
[] ++ x ~ τ0 = [] ->
value (open x body) \/
(existst', beta_step (open x body) t') Jbody: forallx,
x `notin` L -> [] ++ x ~ τ0 ⊢ open x body : τ2
L: AtomSet.t τ0, τ2: typ body: term IHbody: forallx,
x `notin` L ->
[] ++ x ~ τ0 = [] ->
value (open x body) \/
(existst', beta_step (open x body) t') Jbody: forallx,
x `notin` L -> [] ++ x ~ τ0 ⊢ open x body : τ2
L: AtomSet.t τ0, τ2: typ body: term IHbody: forallx,
x `notin` L ->
[] ++ x ~ τ0 = [] ->
value (open x body) \/
(existst', beta_step (open x body) t') Jbody: forallx,
x `notin` L -> [] ++ x ~ τ0 ⊢ open x body : τ2