Library Binding

Require Import List TheoryList Eqdep Omega.

Set Implicit Arguments.

Theorem eq_rec_r_ident : forall (A : Type) (x : A) (P : A -> Set)
  (H : P x) (H0 : x = x), eq_rec_r P H H0 = H.
  intros.
  rewrite (UIP_refl _ _ H0).
  trivial.
Qed.

Theorem eq_rect_r_ident : forall (A : Type) (x : A) (P : A -> Type)
  (H : P x) (H0 : x = x), eq_rect_r P H H0 = H.
  intros.
  rewrite (UIP_refl _ _ H0).
  trivial.
Qed.

Theorem eq_rect_ident : forall (A : Type) (x : A) (P : A -> Type)
  (H : P x) (H0 : x = x), eq_rect _ P H _ H0 = H.
  intros.
  rewrite (UIP_refl _ _ H0).
  trivial.
Qed.

Section Subst.
   Variable dom : Set.
   Variable denote : dom -> Type.

  Inductive Var : list dom -> dom -> Set :=
    | First : forall G t, Var (t :: G) t
    | Next : forall G t t', Var G t -> Var (t' :: G) t.

  Inductive Subst : list dom -> Type :=
    | SNil : Subst nil
    | SCons : forall t G, denote t -> Subst G -> Subst (t :: G).

  Definition head : forall t G, Subst (t :: G) -> denote t.
    inversion 1; subst; trivial.
  Defined.

  Definition tail : forall t G, Subst (t :: G) -> Subst G.
    inversion 1; subst; trivial.
  Defined.

  Fixpoint VarDenote (G : list dom) (t : dom) (v : Var G t) {struct v}
    : Subst G -> denote t :=
      match v in (Var G t) return (Subst G -> denote t) with
        | First _ _ => fun s => head s
        | Next _ _ _ v => fun s => VarDenote v (tail s)
      end.

  Lemma Subst_invert_nil'
    : forall P : Subst nil -> Type,
      P SNil ->
      forall G s, match G return (Subst G -> _) with
                    | nil => P
                    | _ => fun _ => True
                  end s.
    intros.
    destruct s; trivial.
  Qed.

  Theorem Subst_invert_nil
    : forall P : Subst nil -> Type,
      P SNil ->
      forall s, P s.
    intros.
    generalize (Subst_invert_nil' P); intuition.
    generalize (X1 nil); auto.
  Qed.

  Lemma Subst_invert_cons'
    : forall P : forall t G, Subst (t :: G) -> Type,
      (forall (t : dom) (G : list dom) (d : denote t) (s : Subst G),
        P t G (SCons d s))
      -> forall G s, match G return (Subst G -> Type) with
                       | nil => fun _ => True
                       | _ => P _ _
                     end s.
    intros.
    destruct s; trivial.
  Qed.

  Theorem Subst_invert_cons
    : forall P : forall t G, Subst (t :: G) -> Type,
      (forall (t : dom) (G : list dom) (d : denote t) (s : Subst G),
        P t G (SCons d s))
      -> forall t G (s : Subst (t :: G)), P _ _ s.
    intros.
    generalize (Subst_invert_cons' P); intuition.
    generalize (X1 (t :: G)); auto.
  Qed.

  Theorem inversion_Subst_nil : forall (s : Subst nil),
    s = SNil.
    intros.
    pattern s.
    apply Subst_invert_nil.
    trivial.
  Qed.

  Theorem inversion_Subst_cons : forall t G (s : Subst (t :: G)),
    exists v, exists s', s = SCons v s'.
    intros.
    pattern t, G, s.
    apply Subst_invert_cons.
    eauto.
  Qed.
End Subst.

Ltac inversion_Subst_nil ls :=
  let His := fresh "His" in
    (generalize (inversion_Subst_nil ls); intro His;
      subst; simpl in *; unfold eq_rect_r in *; simpl in *).

Ltac inversion_Subst_cons ls :=
  let His := fresh "His"
    with h := fresh "h"
    with t := fresh "t" in
    (destruct (inversion_Subst_cons ls) as [h [t His]];
      subst; simpl in *;
        repeat rewrite eq_rect_r_ident; repeat rewrite eq_rect_ident).

Ltac inversion_Subst s := inversion_Subst_nil s || inversion_Subst_cons s.

Ltac inversion_Subst_any :=
  match goal with
    | [ ls : Subst _ nil |- _ ] => inversion_Subst_nil ls
    | [ ls : Subst _ (_ :: _) |- _ ] => inversion_Subst_cons ls
  end.

Section Var_invert.
   Variable dom : Set.

  Lemma Var_invert'
    : forall P : forall (t' : dom) l t, Var (t' :: l) t -> Prop,
      (forall G t, P t G t (First G t)) ->
      (forall G t t' v,
        P t' G t (Next t' v)) ->
      forall l t v,
        match l return (Var l t -> Prop) with
          | nil => fun _ => True
          | _ => fun v => P _ _ _ v
        end v.
    intros.
    destruct v; auto.
  Qed.

  Theorem Var_invert
    : forall P : forall (t' : dom) l t, Var (t' :: l) t -> Prop,
      (forall G t, P t G t (First G t)) ->
      (forall G t t' v,
        P t' G t (Next t' v)) ->
      forall t' l t v, P t' l t v.
    intros.
    generalize (Var_invert' P).
    intuition.
    generalize (H1 (t' :: l)).
    trivial.
  Qed.

  Definition liftVar' : forall (G : list dom) t G', Var (G ++ G') t
    -> forall t', Var (G ++ t' :: G') t.
    induction G; simpl; intuition.
    apply Next; trivial.
    inversion H; subst.
    apply First.
    apply Next.
    auto.
  Defined.

  Definition liftVar (G : list dom) (t : dom) (v : Var G t) (t' : dom) : Var (t' :: G) t :=
    liftVar' nil G v t'.

   Section substVar.
     Variable dom2 : Set.

     Variable term : list dom -> dom2 -> Set.
     Variable inj : dom -> dom2.
     Variable var : forall G t, Var G t -> term G (inj t).

     Variable lift : forall a G t, term G t -> term (a :: G) t.

    Definition substVar' : forall (G : list dom) t' G' t, Var (G ++ t' :: G') t
      -> term G' (inj t') -> term (G ++ G') (inj t).
      induction G; simpl; intuition.

      inversion H; subst.

      exact H0.

      apply var; exact H4.

      inversion H; subst.

      apply var.
      apply First.
      
      apply lift.
      apply IHG with t'.
      exact H4.
      exact H0.
    Defined.

    Definition substVar : forall t' (G : list dom) t, Var (t' :: G) t
      -> term G (inj t') -> term G (inj t).
      intros t' G t v e.
      exact (substVar' nil v e).
    Defined.
   End substVar.

  Definition retype_Var : forall t t', t = t'
    -> forall G, Var (dom:= dom) G t
      -> Var G t'.
    intros; subst; trivial.
  Defined.

  Theorem retype_Var_ident : forall G t (H : t = t) (k : Var G t),
    retype_Var H k = k.
    intros.
    unfold retype_Var.
    rewrite eq_rec_r_ident.
    trivial.
  Qed.

  Lemma Var_split : forall t G t' (v : Var (t :: G) t'),
    (t = t' /\ forall Heq : t = t', v = retype_Var Heq (First _ _))
    \/ exists v', v = Next _ v'.
    intros.
    pattern t, G, t', v.
    apply Var_invert; simpl; intuition.

    left; intuition.
    rewrite retype_Var_ident; trivial.

    eauto.
  Qed.
End Var_invert.

Ltac inversion_Var elm :=
  let Heq := fresh "Heq"
    with His := fresh "His"
    with v' := fresh "v'" in
    (destruct (Var_split elm) as [[Heq His] | [v' His]];
      [subst; generalize (His (refl_equal _)); clear His; intro His; repeat rewrite retype_Var_ident in His | idtac];
      subst; simpl in *;
        repeat rewrite eq_rect_r_ident; repeat rewrite eq_rect_ident);
    repeat rewrite eq_rect_ident.

Ltac inversion_Var_any :=
  match goal with
    | [ v : Var _ _ |- _ ] => inversion v; fail
    | [ v : Var _ _ |- _ ] => inversion_Var v
  end.

Ltac simpl_Binding := repeat progress
  (repeat inversion_Subst_any;
    repeat inversion_Var_any;
      simpl in *; intuition).

Section VarConvert.
   Variables dom1 dom2 : Set.
   Variable convert : dom1 -> dom2.

  Fixpoint VarConvert (G : list dom1) (t : dom1) (v : Var G t) {struct v}
    : Var (map convert G) (convert t) :=
    match v in (Var G t) return (Var (map convert G) (convert t)) with
      | First _ _ => First _ _
      | Next _ _ _ v' => Next _ (VarConvert v')
    end.
End VarConvert.

Section Subst_lr.
   Variables dom1 dom2 : Set.
   Variable denote1 : dom1 -> Type.
   Variable denote2 : dom2 -> Type.
   Variable compile : dom1 -> dom2.
   Variable val_lr : forall (t : dom1), denote1 t -> denote2 (compile t) -> Prop.

  Inductive Subst_lr : forall G, Subst denote1 G -> Subst denote2 (map compile G) -> Prop :=
    | Slr_Nil : Subst_lr (SNil _) (SNil _)
    | Slr_Cons : forall t G (v : denote1 t) (s : Subst _ G) cv cs,
      val_lr v cv
      -> Subst_lr s cs
      -> Subst_lr (SCons _ v s) (SCons _ cv cs).

  Lemma Subst_lr_Var : forall G t (v : Var G t) s s',
    Subst_lr s s'
    -> val_lr (VarDenote v s) (VarDenote (VarConvert compile v) s').
    induction 1; simpl; intuition;
      inversion_Var_any; simpl; intuition.
  Qed.

  Definition liftSubst' : forall G G', Subst denote1 (G ++ G')
    -> forall t, denote1 t -> Subst denote1 (G ++ t :: G').
    induction G; simpl; intuition.
    
    constructor.
    exact X0.
    exact X.
    
    inversion X; subst.
    constructor.
    exact X1.
    eauto.
  Defined.

  Theorem liftSubst'_sound : forall G G' (s : Subst denote1 (G ++ G'))
    t' (v0 : denote1 t')
    t (v : Var (G ++ G') t),
    VarDenote (liftVar' G G' v t') (liftSubst' _ _ s v0) =
    VarDenote v s.
    induction G; simpl_Binding.
  Qed.
End Subst_lr.

Ltac rewriteEverywhere H :=
  try rewrite H;
    repeat match goal with
             | [ H' : _ |- _ ] => rewrite H in H'
           end;
    clear H.

Ltac rewriteNat :=
  match goal with
    | [ H : _ = O |- _ ] => rewriteEverywhere H
    | [ H : _ = S _ |- _ ] => rewriteEverywhere H
  end.

Ltac simplify' := repeat progress (simpl in *;
  repeat rewrite eq_rect_r_ident; intuition).

Ltac rewriteOnce tac :=
  match goal with
    | [ H : _ |- _ ] =>
      (rewrite H; tac; fail)
      || (rewrite <- H; tac; fail)
  end.

Ltac simplify := simplify'; try rewriteOnce ltac:(auto; try omega; rewriteOnce ltac:(auto; omega));
  intuition eauto.

Ltac forward' self search_context search_goal is_relevant H :=
  match type of H with
    | ?T =>
      match goal with
        | [ H : ?T1 -> _ |- _ ] =>
          match type of H with
            | T => idtac
          end;
          match type of T1 with
            | Prop => idtac
          end;
          let pf := fresh "pf" in
            (assert (pf : T1);
              [eauto; fail | generalize (H pf); clear H; intro H; self H])
        | [ H : forall (s : ?T1), _ |- _ ] =>
          match type of H with
            | T => idtac
          end;
          search_context T1;
          match goal with
            | [ x : _ |- _ ] =>
              generalize (H x); clear H; intro H; self H
          end
        | [ H : forall (s : ?T1), _ |- _ ] =>
          match type of H with
            | T => idtac
          end;
          search_goal T1;
          match goal with
            | [ |- context[?E] ] =>
              generalize (H E); clear H; intro H; self H
          end
        | _ => is_relevant T
      end
  end.

Ltac forward search_context search_goal is_relevant H :=
  forward' ltac:(forward ltac:search_context ltac:search_goal ltac:is_relevant)
  ltac:search_context ltac:search_goal ltac:is_relevant H.

Ltac check_eq E1 E2 :=
  let dummy := fresh "dummy" in
    (assert (dummy : E1 = E2);
      [reflexivity | clear dummy]).

Ltac crush search_context search_goal is_relevant simplifier solver :=
  repeat (simplifier;
    match goal with
      | [ H : forall x, _ |- _ ] =>
        forward ltac:search_context ltac:search_goal ltac:is_relevant H
    end;
    solver).

Index
This page has been generated by coqdoc