Generic variable binding support |
Require
Import
Arith Omega.
Require
Import
Max.
Set Implicit
Arguments.
Definition
var := nat.
Definition
var_eq_dec := eq_nat_dec.
Ltac
wrong := assert False; [idtac | tauto].
Section
Contexts.
Variable
term : Set.
Inductive
context : Set :=
| Empty : context
| Bind : context -> var -> term -> context.
Notation
"G , x <: t" := (Bind G x t) (left associativity, at level 40).
Well-formedness |
Inductive
inContext : var -> term -> context -> Prop :=
| In_Eq : forall x t G, inContext x t (G, x <: t)
| In_Neq : forall x t G x' t', inContext x t G
-> inContext x t (G, x' <: t').
Hint
Constructors inContext.
Notation
"[ x <: t ] \in G" := (inContext x t G) (at level 50).
Definition
inDom x G := exists t, [x <: t] \in G.
Notation
"x \in G" := (inDom x G) (at level 50).
Variable
wfTerm : context -> term -> Prop.
Notation
"G |-- t 'ok'" := (wfTerm G t) (at level 50).
Reserved Notation
"|-- G 'ok'" (at level 50).
Inductive
wfContext : context -> Prop :=
| WF_Empty : |-- Empty ok
| WF_Bind : forall G x t,
|-- G ok
-> ~(x \in G)
-> G |-- t ok
-> |-- (G, x <: t) ok
where "|-- G 'ok'" := (wfContext G).
Hint
Constructors wfContext.
Permutation and weakening |
Inductive
insertInto : var -> term -> context -> context -> Prop :=
| II_Head : forall x t G,
G |-- t ok
-> insertInto x t G (G, x <: t)
| II_Skip : forall x t G x' t' G',
insertInto x t G G'
-> insertInto x t (G, x' <: t') (G', x' <: t').
Hint
Constructors insertInto.
Inductive
permute : context -> context -> Prop :=
| PM_Empty : permute Empty Empty
| PM_Bind : forall G x t G' G'',
permute G G'
-> insertInto x t G' G''
-> permute (G, x <: t) G''.
Hint
Constructors permute.
Lemma
insertInto_inContext : forall x t G G',
insertInto x t G G'
-> forall x' t', [x' <: t'] \in (G, x <: t)
-> [x' <: t'] \in G'.
induction 1; intuition.
inversion H0; subst; eauto.
inversion H4; subst; eauto.
Qed
.
Lemma
permute_inContext : forall G D,
permute G D
-> forall x t, [x <: t] \in G
-> [x <: t] \in D.
induction 1; intuition.
apply insertInto_inContext with x t G'; trivial.
inversion H1; subst; auto.
Qed
.
Lemma
permute_inDom : forall G D,
permute G D
-> forall x, x \in G
-> x \in D.
unfold inDom.
generalize permute_inContext.
firstorder.
Qed
.
Lemma
permute_inDom_neg : forall G D,
permute G D
-> forall x, ~x \in D
-> ~x \in G.
generalize permute_inDom.
firstorder.
Qed
.
Hint
Resolve permute_inContext permute_inDom permute_inDom_neg.
Lemma
insertInto_inContext' : forall x t G G',
insertInto x t G G'
-> forall x' t', [x' <: t'] \in G'
-> [x' <: t'] \in (G, x <: t).
induction 1; intuition.
inversion H0; subst; eauto.
generalize (IHinsertInto _ _ H4); intro Hin.
inversion Hin; subst; auto.
Qed
.
Lemma
permute_inContext' : forall G D,
permute G D
-> forall x t, [x <: t] \in D
-> [x <: t] \in G.
induction 1; intuition.
generalize (insertInto_inContext' H0 H1); intro Hin.
inversion Hin; subst; auto.
Qed
.
Lemma
permute_inDom' : forall G D,
permute G D
-> forall x, x \in D
-> x \in G.
unfold inDom.
generalize permute_inContext'.
firstorder.
Qed
.
Hint
Resolve permute_inDom'.
Hypothesis
preweaken_wfTerm : forall G t,
G |-- t ok
-> forall D, (forall x, x \in G -> x \in D)
-> D |-- t ok.
Lemma
permute_wfTy : forall G t,
G |-- t ok
-> forall D, permute G D
-> D |-- t ok.
eauto.
Qed
.
Hint
Resolve permute_wfTy.
Lemma
inDom_Bind : forall x t G,
[x <: t] \in G
-> forall x' t', [x <: t] \in G, x' <: t'.
eauto.
Qed
.
Lemma
inContext_Bind : forall x G,
x \in G
-> forall x' t', x \in G, x' <: t'.
generalize inDom_Bind.
firstorder.
Qed
.
Lemma
inContext_Bind_neg : forall x G x' t',
~(x \in G, x' <: t')
-> ~(x \in G).
intros.
intro.
apply H.
apply inContext_Bind; trivial.
Qed
.
Hint
Resolve inContext_Bind inContext_Bind_neg.
Fixpoint
weaken (G1 G2 : context) {struct G2} : context :=
match G2 with
| Empty => G1
| G2', x <: t => (weaken G1 G2'), x <: t
end.
Infix
"++" := weaken (left associativity, at level 40).
Lemma
weaken_inContext : forall G x t,
[x <: t] \in G
-> forall D, |-- (G ++ D) ok
-> [x <: t] \in (G ++ D).
induction D; simpl; auto.
inversion 1; subst; auto.
Qed
.
Lemma
weaken_inDom : forall G x,
x \in G
-> forall D, |-- (G ++ D) ok
-> x \in (G ++ D).
generalize weaken_inContext; firstorder.
Qed
.
Hint
Resolve weaken_inContext weaken_inDom.
Lemma
permute_refl : forall G,
|-- G ok
-> permute G G.
induction 1; eauto.
Qed
.
Hint
Resolve permute_refl.
Lemma
weaken_wfTy : forall G t,
G |-- t ok
-> forall D, |-- (G ++ D) ok
-> G ++ D |-- t ok.
eauto.
Qed
.
Hint
Resolve weaken_wfTy.
Lemma
insertInto_inContext2 : forall x t G G',
insertInto x t G G'
-> forall x' t', [x' <: t'] \in G
-> [x' <: t'] \in G'.
induction 1; intuition.
inversion H0; subst; eauto.
Qed
.
Hint
Resolve insertInto_inContext2.
Lemma
insertInto_inDom : forall x t G G',
insertInto x t G G'
-> forall x', x' \in G
-> x' \in G'.
intros.
destruct H0.
red.
eauto.
Qed
.
Lemma
insertInto_wfTy : forall x t G G',
insertInto x t G G'
-> |-- G ok
-> forall t', G |-- t' ok
-> G' |-- t' ok.
eauto 6.
Qed
.
Lemma
insertInto_wfContext : forall x t G G',
insertInto x t G G'
-> |-- G ok
-> ~x \in G
-> |-- G' ok.
induction 1; auto.
inversion 1; subst.
intro Hin.
constructor; eauto.
intro.
destruct H1 as [t'' Ht''].
generalize (insertInto_inContext' H Ht''); intro Hin'.
inversion Hin'; subst.
apply Hin; exists t'; auto.
apply H5.
exists t''; auto.
eapply insertInto_wfTy; eauto.
Qed
.
Hint
Resolve insertInto_wfContext.
Lemma
permute_wfContext : forall G D,
permute G D
-> |-- G ok
-> |-- D ok.
induction 1; inversion 1; subst; eauto.
eapply insertInto_wfContext; eauto.
Qed
.
Hint
Resolve permute_wfContext.
Lemma
split_inDom : forall x G y t,
x \in G, y <: t
-> x = y \/ (x \in G).
intros.
destruct H as [t' Ht'].
inversion Ht'; subst; auto.
right.
exists t'; auto.
Qed
.
Lemma
head_inDom : forall x G t,
x \in G, x <: t.
intros.
exists t; auto.
Qed
.
Lemma
cons_inDom : forall x G y t,
x \in G
-> x \in G, y <: t.
intros.
destruct H as [t' Ht'].
exists t'; auto.
Qed
.
Hint
Resolve head_inDom cons_inDom.
Lemma
multiSwap : forall G x t D,
|-- G ++ D ok
-> ~x \in G ++ D
-> G |-- t ok
-> permute (G, x <: t ++ D) (G ++ D, x <: t).
induction D; simpl; intuition.
apply PM_Bind with (G ++ D, x <: t).
inversion H; subst.
apply IHD; eauto.
inversion H; subst.
eauto.
Qed
.
Hint
Resolve multiSwap.
Lemma
multiSwap' : forall G x t D,
|-- G ++ D ok
-> ~x \in G ++ D
-> G |-- t ok
-> permute (G ++ D, x <: t) (G, x <: t ++ D).
induction D; simpl; intuition.
apply PM_Bind with (G ++ D, v <: t0); auto.
apply II_Skip.
clear IHD H H0.
induction D; simpl; intuition.
Qed
.
Hint
Resolve multiSwap'.
Lemma
move_wfContext : forall G t,
G |-- t ok
-> forall D, |-- G ++ D ok
-> forall x, ~x \in G ++ D
-> |-- G, x <: t ++ D ok.
induction D; simpl; intuition.
inversion H0; subst.
constructor; eauto.
intro.
assert (v \in G ++ D, x <: t).
apply permute_inDom with (G, x <: t ++ D); auto.
destruct (split_inDom H3); subst; auto.
apply preweaken_wfTerm with (G ++ D); intuition.
apply permute_inDom with (G ++ D, x <: t); auto.
Qed
.
Hint
Resolve move_wfContext.
Lemma
weaken_inContext2 : forall x t G D,
[x <: t] \in G ++ D
-> [x <: t] \in G \/ [x <: t] \in D.
induction D; simpl; intuition.
inversion H; subst; eauto.
intuition.
Qed
.
Lemma
weaken_inDom2 : forall x G D,
x \in G ++ D
-> x \in G \/ x \in D.
generalize weaken_inContext2; firstorder.
Qed
.
Lemma
weaken_inContext3 : forall x t G D,
[x <: t] \in G
-> [x <: t] \in G ++ D.
induction D; simpl; intuition.
Qed
.
Lemma
weaken_inDom3 : forall x G D,
x \in G
-> x \in G ++ D.
generalize weaken_inContext3; firstorder.
Qed
.
Lemma
weaken_inContext4 : forall x t G D,
[x <: t] \in D
-> [x <: t] \in G ++ D.
induction D; simpl; intuition.
inversion H.
inversion H; simpl; eauto.
Qed
.
Lemma
weaken_inDom4 : forall x G D,
x \in D
-> x \in G ++ D.
generalize weaken_inContext4; firstorder.
Qed
.
Hint
Resolve weaken_inDom2 weaken_inDom3 weaken_inDom4.
Lemma
narrowing_wfTerm : forall G x t1 D t,
G, x <: t1 ++ D |-- t ok
-> forall t2, G, x <: t2 ++ D |-- t ok.
intros.
apply preweaken_wfTerm with (G, x <: t1 ++ D); intuition.
destruct (weaken_inDom2 _ _ H0); eauto.
destruct (split_inDom H1); subst; eauto.
Qed
.
Hint
Resolve narrowing_wfTerm.
Lemma
narrowing_inDom : forall v G x t1 D,
v \in G, x <: t1 ++ D
-> forall t2, v \in G, x <: t2 ++ D.
induction D; simpl; intuition;
destruct (split_inDom H); subst; eauto.
Qed
.
Hint
Resolve narrowing_inDom.
Lemma
narrowing_wfContext : forall G x t1 D,
|-- G, x <: t1 ++ D ok
-> forall t2, G |-- t2 ok
-> |-- G, x <: t2 ++ D ok.
intros.
induction D; simpl in *; intuition.
inversion H; subst; auto.
inversion H; subst.
constructor; eauto.
Qed
.
Hint
Resolve narrowing_wfContext.
Lemma
notBound_weaken : forall G x t D,
|-- G, x <: t ++ D ok
-> ~x \in G.
induction D; simpl; intuition;
inversion H; auto.
Qed
.
Hint
Resolve notBound_weaken.
Lemma
inContext_contra : forall x t G,
[x <: t] \in G
-> ~x \in G
-> False.
intros.
apply H0.
red.
eauto.
Qed
.
Hint
Resolve inContext_contra.
Lemma
inContext_inDom : forall x t G,
[x <: t] \in G
-> x \in G.
intros.
red; eauto.
Qed
.
Lemma
wfContext_invert1 : forall G x t,
|-- G, x <: t ok
-> |-- G ok.
inversion 1; trivial.
Qed
.
Hint
Resolve wfContext_invert1.
Lemma
squeeze_inContext : forall v G t D,
[v <: t] \in G, v <: t ++ D.
induction D; simpl; intuition.
Qed
.
Lemma
squeeze_inDom : forall v G t D,
v \in G, v <: t ++ D.
generalize squeeze_inContext; firstorder.
Qed
.
Hint
Resolve squeeze_inDom.
Lemma
narrowing_eq : forall x t D G t',
|-- G, x <: t' ++ D ok
-> [x <: t] \in G, x <: t' ++ D
-> t = t'.
induction D; simpl; intuition.
inversion H0; subst; trivial.
wrong.
inversion H; eauto.
inversion H0; subst; eauto.
wrong.
inversion H; subst.
auto.
Qed
.
Lemma
weaken_bind_assoc : forall D G v t,
G ++ (D, v <: t) = G ++ D, v <: t.
induction D; simpl; intuition.
Qed
.
Lemma
wfContext_invert_weaken : forall D G,
|-- G ++ D ok
-> |-- G ok.
induction D; intuition.
rewrite weaken_bind_assoc in H.
eauto.
Qed
.
Hint
Resolve wfContext_invert_weaken.
Lemma
narrowing_neq : forall x t G x' t' D,
[x <: t] \in G, x' <: t' ++ D
-> x <> x'
-> forall t'', [x <: t] \in G, x' <: t'' ++ D.
induction D; simpl; intuition;
inversion H; subst; intuition.
Qed
.
Hint
Resolve narrowing_neq.
Lemma
switchBase_inDom : forall x G x' t D,
(forall x0, x0 \in G -> x0 \in D)
-> x \in G, x' <: t
-> x \in D, x' <: t.
intros.
destruct (split_inDom H0); subst; eauto.
Qed
.
Lemma
switchTerm_inDom : forall x G x' t t',
x \in G, x' <: t
-> x \in G, x' <: t'.
intros.
destruct (split_inDom H); subst; eauto.
Qed
.
Lemma
switchWeaken_inDom' : forall D x G,
x \in G ++ D
-> forall G', (forall x, x \in G -> x \in G')
-> x \in G' ++ D.
induction D; simpl; intuition.
destruct (split_inDom H); subst; eauto.
Qed
.
Lemma
switchWeaken_inDom : forall D x x' t G,
x \in G, x' <: t ++ D
-> forall t', x \in G, x' <: t' ++ D.
intros.
eapply switchWeaken_inDom'; eauto.
intros.
destruct (split_inDom H0); subst; eauto.
Qed
.
End
Contexts.
Infix
"++" := weaken (left associativity, at level 40).
Hint
Constructors inContext wfContext insertInto permute.
Hint
Resolve permute_inContext.
Hint
Resolve weaken_inContext weaken_inContext2 weaken_inContext3 weaken_inContext4.
Hint
Resolve permute_inDom weaken_inDom inContext_inDom.
Hint
Resolve switchTerm_inDom switchBase_inDom switchWeaken_inDom.
Hint
Resolve permute_wfContext move_wfContext wfContext_invert_weaken.
Hint
Resolve multiSwap multiSwap'.
Hint
Resolve narrowing_wfContext narrowing_neq.
Ltac
narrowing_eq :=
repeat match goal with
| [ H : inContext ?x0 ?u (Bind ?G ?x0 ?v ++ ?D) |- _ ] =>
assert (u = v);
[eapply narrowing_eq; eauto; fail
| subst; clear H]
end.
Ltac
binding_simpl := repeat progress (simpl in *; narrowing_eq; subst; try discriminate).