Rocoma.Recipes_directly_box

Directly boxed subrecipes



Fixpoint directly_box containee container :=
  match container with
  | Top | Var _ | Zero => False
  | And s t
  | App s t => directly_box containee s \/ directly_box containee t
  | TLam s
  | TAll s
  | Neu s
  | Imp s _
  | Lam s _
  | TApp s _ => directly_box containee s
  | Box s => s = containee
  end.

(* The predicate db u s n states that u is directly_boxed in s and
   below n recipe binders. *)

(*?*) Inductive db : recipe -> recipe -> nat -> Prop :=
(*?*) | db_box u s : u = s -> db u (Box s) 0
(*?*) | db_lam u s U n : db u s n -> db u (Lam s U) n.+1
(*?*) | db_andl u s t n : db u s n -> db u (And s t) n
(*?*) | db_andr u s t n : db u t n -> db u (And s t) n
(*?*) | db_appl u s t n : db u s n -> db u (App s t) n
(*?*) | db_appr u s t n : db u t n -> db u (App s t) n
(*?*) | db_tlam u s n : db u s n -> db u (TLam s) n
(*?*) | db_tall u s n : db u s n -> db u (TAll s) n
(*?*) | db_imp u s f n : db u s n -> db u (Imp s f) n
(*?*) | db_neu u s n : db u s n -> db u (Neu s) n
(*?*) | db_tapp u s T n : db u s n -> db u (TApp s T) n.
(*?*)
(*?*) Lemma directly_box_db_coincide u s :
(*?*) directly_box u s <-> exists n, db u s n.
(*?*) Proof.
(*?*) elim: s u =>/=.
(*?*) - by move=> *; split=>//; move=> [n h]; inv h.
(*?*) - by move=> *; split=>//; move=> [n h]; inv h.
(*?*) - by move=> *; split=>//; move=> [n h]; inv h.
(*?*) - move=> s h1 t h2 u; split.
(*?*) + move=> [hs|ht].
(*?*) by have[n hn]:= (proj1 (h1 u) hs); exists n; constructor.
(*?*) by have[n hn]:= (proj1 (h2 u) ht); exists n; constructor.
(*?*) + move=> [n hn]. inv hn.
(*?*) by left; apply h1; exists n.
(*?*) by right; apply h2; exists n.
(*?*) - move=> s h1 t h2 u; split.
(*?*) + move=> [hs|ht].
(*?*) by have[n hn]:= (proj1 (h1 u) hs); exists n; constructor.
(*?*) by have[n hn]:= (proj1 (h2 u) ht); exists n; constructor.
(*?*) + move=> [n hn]. inv hn.
(*?*) by left; apply h1; exists n.
(*?*) by right; apply h2; exists n.
(*?*) - move=> s h1 T u; split.
(*?*) + move=> h.
(*?*) by have[n hn]:= (proj1 (h1 u) h); exists n; constructor.
(*?*) + move=> [n hn]. inv hn.
(*?*) by apply h1; exists n.
(*?*) - move=> s h1 U u; split.
(*?*) + move=> h.
(*?*) by have[n hn]:= (proj1 (h1 u) h); exists n.+1; constructor.
(*?*) + move=> [m hn]. inv hn.
(*?*) by apply h1; exists n.
(*?*) - move=> s h1 ? u; split.
(*?*) + move=> h.
(*?*) by have[n hn]:= (proj1 (h1 u) h); exists n; constructor.
(*?*) + move=> [n hn]. inv hn.
(*?*) by apply h1; exists n.
(*?*) - move=> s h1 u; split.
(*?*) + move=> h.
(*?*) by have[n hn]:= (proj1 (h1 u) h); exists n; constructor.
(*?*) + move=> [n hn]. inv hn.
(*?*) by apply h1; exists n.
(*?*) - move=> s h1 u; split.
(*?*) + move=> h.
(*?*) by have[n hn]:= (proj1 (h1 u) h); exists n; constructor.
(*?*) + move=> [n hn]. inv hn.
(*?*) by apply h1; exists n.
(*?*) - move=> s h1 u; split=> [e|[n hn]].
(*?*) + apply h1 in e as [n hn]. exists n. by constructor.
(*?*) + inv hn. apply h1. by exists n.
(*?*) - move=> s h1 u; split=> [e|[n hn]]//.
(*?*) + eexists. by constructor.
(*?*) + by inv hn.
(*?*) Qed.

There exists some prefix δ st. Γ = δ .: Δ
Definition ctx_ext (Γ Δ: ctx) :=
  exists len, forall i, Γ (i + len) = Δ i.

Lemma ctx_ext0 Γ :
  ctx_ext Γ Γ.
Proof.
  exists 0=> i.
  by rewrite addn0.
Qed.

Lemma ctx_ext1 Δ U Γ :
  ctx_ext Δ (U .: Γ) ->
  ctx_ext Δ Γ.
Proof.
  move=> [len h].
  exists len.+1=> x.
  by rewrite -addSnnS h.
Qed.

The high end of the window depends on the depth of the box.
Lemma directly_box_ty_ext r s Γ U a b :
  [ Γ, a, b ⊢ r :- U ] ->
  directly_box s r ->
  exists Δ V c, [ Δ, 0, c ⊢ s :- V ] /\ ctx_ext Δ Γ.
Proof.
  move=> h.
  elim: h s=>{r Γ U a b}; try by move=> //=.
  - by move=> > ????? [] h; eauto.
  - by move=> > ????? [] h; eauto.
  - move=> ??????? h3 ? /= h4.
    have{h3 h4}[D [U [c [? h]]]]:= (h3 _ h4).
    exists D, U, c; split=>//.
    by apply ctx_ext1 in h.
  - move=> Γ a b u U hc hty ih t /= <-.
    exists Γ, U, b. split=>//.
    exact: ctx_ext0.
Qed.

Lemma directly_box_dec ee er : decidable (directly_box ee er).
Proof.
  elim: er=>//=; try (by left); try (by right).
  - move=> > [] ? > [] ?;
    try by (left; tauto);
    try by (right; tauto).
    right.
    by case; eauto.
  - move=> > [] ? > [] ?;
    try by (left; tauto);
    try by (right; tauto).
    right.
    by case; eauto.
  - move=> *. exact: recipe_eq_dec.
Qed.

Lemma directly_box_ty r s U Γ a b :
  [ Γ, a, b ⊢ r :- U ] ->
  directly_box s r ->
  closed s ->
  exists V, [ ⊢ s :- V ].
Proof.
  elim: r s U Γ a b =>//.
  - by move=> > ? > ? > hty /= []*; inv hty; eauto.
  - by move=> > ? > ? > hty /= []*; inv hty; eauto.
  - by move=> > ? > hty /= *; inv hty; eauto.
  - by move=> > ? > hty /= *; inv hty; eauto.
  - by move=> > ? > hty /= *; inv hty; eauto.
  - by move=> > ? > hty /= *; inv hty; eauto.
  - by move=> > ? > hty /= *; inv hty; eauto.
  - by move=> > ? > hty /= *; inv hty; eauto.
  - move=> s hs u U Γ a b hty /= <- hc.
    exists U. inv hty.
    apply (has_type_lower_b (b:=b))=>//.
    by apply closed_has_ty_contr with Γ.
Qed.

Lemma directly_box_depth n s r :
  depth r <= n.+1 ->
  directly_box s r ->
  depth s <= n.
Proof.
  elim: r s n; try by move=>//=.
  - move=> s hs t ht ? n /= ? [] *.
    + have h: depth s <= n.+1 by lia.
      exact: (hs _ _ h).
    + have h: depth t <= n.+1 by lia.
      exact: (ht _ _ h).
  - move=> s hs t ht ? n /= ? [] *.
    + have h: depth s <= n.+1 by lia.
      by apply (hs _ _ h).
    + have h: depth t <= n.+1 by lia.
      exact: (ht _ _ h).
  - move=> ???? /= ? <-.
    by lia.
Qed.

subterm sub r holds when sub occurs somewhere in r, boxes included. Same argument order as directly_box: the contained recipe comes first.
Fixpoint subterm sub r :=
  sub = r \/
  match r with
  | Top | Var _ | Zero => False
  | And s t
  | App s t => subterm sub s \/ subterm sub t
  | TLam s
  | TAll s
  | Neu s
  | Imp s _
  | Lam s _
  | Box s
  | TApp s _ => subterm sub s
  end.

Lemma subterm_refl s :
  subterm s s.
Proof.
  by case: s=>/=; by left.
Qed.

Lemma subterm_directly_box s t :
  directly_box s t ->
  subterm s t.
Proof.
  elim: t=>//=; try by auto.
  - by move=> u hu t ht []?; auto.
  - by move=> u hu t ht []?; auto.
  - move=> u hu e. subst. right. by apply subterm_refl.
Qed.

Lemma subterm_neu_idempotent s r :
  subterm s (neu r) ->
  s = neu s.
Proof.
  elim: r=>//=.
  - move=> > []? //. by subst.
  - move=> []? //. by subst.
  - move=> []? //. by subst.
  - move=> u hu t ht [|[]]?; [|by auto|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu t ht [|[]]?; [|by auto|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu S []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu S []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu S []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
  - move=> u hu []?; [|by auto].
    subst=>/=. by rewrite !neu_idempotent.
Qed.

Corollary directly_box_neu_idempotent s r :
  directly_box s (neu r) ->
  s = neu s.
Proof.
  move/subterm_directly_box.
  by apply subterm_neu_idempotent.
Qed.

Lemma directly_box_neu s t :
  directly_box s t ->
  directly_box (neu s) (neu t).
Proof.
  elim: t s=>//=.
  - by move=> s h1 t h2 u []h; [left|right]; auto.
  - by move=> s h1 t h2 u []h; [left|right]; auto.
  - by move=> s h1 u ->.
Qed.

Fixpoint mem_box r :=
  match r with
  | Top | Var _ | Zero => False
  | And s t
  | App s t => mem_box s \/ mem_box t
  | TLam s
  | TAll s
  | Neu s
  | Imp s _
  | Lam s _
  | TApp s _ => mem_box s
  | Box _ => True
  end.

Lemma directly_box_mem_box r :
  forall s, directly_box s r -> mem_box r.
Proof.
  elim: r=>//=.
  - move=> > hs > ht r [] *.
    by left; exact: (hs r).
    by right; exact: (ht r).
  - move=> > hs > ht r [] *.
    by left; exact: (hs r).
    by right; exact: (ht r).
Qed.

Lemma mem_box_depth r :
  depth r = 0 -> not (mem_box r).
Proof.
  elim: r=>//=; try by tauto.
  - move=> > hs > ht ? [] *.
    apply hs; by [|lia].
    apply ht; by [|lia].
  - move=> > hs > ht ? [] *.
    apply hs; by [|lia].
    apply ht; by [|lia].
Qed.

Lemma directly_box_closed s r U Γ a b :
  directly_box s r ->
  [ Γ, a, b ⊢ r :- U ] ->
  closed s.
Proof.
  elim: r s U Γ a b;
  try (by move=> > h; inv h).
  - by move=> ???? > /= [hl|hr] ht; inv ht; eauto.
  - by move=> ???? > /= [hl|hr] ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
  - by move=> ?? > /= h0 ht; inv ht; eauto.
Qed.

Inductive db3 : recipe -> recipe -> recipe -> recipe -> recipe -> recipe -> Prop :=
| db_box3 u v w r s t : u = r -> v = s -> w = t -> db3 u v w (Box r) (Box s) (Box t)
| db_lam3 u v w r s t U :
    db3 u v w r s t -> db3 u v w (Lam r U) (Lam s U) (Lam t U)
| db_andl3 u v w r1 r2 s1 s2 t1 t2 :
    db3 u v w r1 s1 t1 ->
    db3 u v w (And r1 r2) (And s1 s2) (And t1 t2)
| db_andr3 u v w r1 r2 s1 s2 t1 t2 :
    db3 u v w r2 s2 t2 ->
    db3 u v w (And r1 r2) (And s1 s2) (And t1 t2)
| db_appl3 u v w r1 r2 s1 s2 t1 t2 :
    db3 u v w r1 s1 t1 ->
    db3 u v w (App r1 r2) (App s1 s2) (App t1 t2)
| db_appr3 u v w r1 r2 s1 s2 t1 t2 :
    db3 u v w r2 s2 t2 ->
    db3 u v w (App r1 r2) (App s1 s2) (App t1 t2)
| db_tlam3 u v w r s t :
    db3 u v w r s t -> db3 u v w (TLam r) (TLam s) (TLam t)
| db_tall3 u v w r s t :
    db3 u v w r s t -> db3 u v w (TAll r) (TAll s) (TAll t)
| db_imp3 u v w r s t f :
    db3 u v w r s t -> db3 u v w (Imp r f) (Imp s f) (Imp t f)
| db_neu3 u v w r s t :
    db3 u v w r s t -> db3 u v w (Neu r) (Neu s) (Neu t)
| db_tapp3 u v w r s t T :
    db3 u v w r s t ->
    db3 u v w (TApp r T) (TApp s T) (TApp t T).

Lemma db3_proj1 u v w r s t :
  db3 u v w r s t ->
  directly_box u r.
Proof.
  elim: r s t;
    by first
     [ move=> > h; inv h
     | move=> ?????? /= h; inv h; [left|right]; eauto
     | move=> ????? /= h; inv h; eauto
     | move=> ???? /= h; inv h; eauto ].
Qed.

Lemma db3_proj2 u v w r s t :
  db3 u v w r s t ->
  directly_box v s.
Proof.
  elim: s r t;
    by first
     [ move=> > h; inv h
     | move=> ?????? /= h; inv h; [left|right]; eauto
     | move=> ????? /= h; inv h; eauto
     | move=> ???? /= h; inv h; eauto ].
Qed.

Lemma db3_proj3 u v w r s t :
  db3 u v w r s t ->
  directly_box w t.
Proof.
  elim: t r s;
    by first
     [ move=> > h; inv h
     | move=> ?????? /= h; inv h; [left|right]; eauto
     | move=> ????? /= h; inv h; eauto
     | move=> ???? /= h; inv h; eauto ].
Qed.