Library Binding

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).

Index
This page has been generated by coqdoc