+ mapOptionTree' (dropVar lv).
+
+Lemma In_both : forall T (l1 l2:list T) a, In a l1 -> In a (app l1 l2).
+ intros T l1.
+ induction l1; intros.
+ inversion H.
+ simpl.
+ inversion H; subst.
+ left; auto.
+ right.
+ apply IHl1.
+ apply H0.
+ Qed.
+
+Lemma In_both' : forall T (l1 l2:list T) a, In a l2 -> In a (app l1 l2).
+ intros T l1.
+ induction l1; intros.
+ apply H.
+ rewrite <- app_comm_cons.
+ simpl.
+ right.
+ apply IHl1.
+ auto.
+ Qed.
+
+Lemma distinct_app : forall T (l1 l2:list T), distinct (app l1 l2) -> distinct l1 /\ distinct l2.
+ intro T.
+ intro l1.
+ induction l1; intros.
+ split; auto.
+ apply distinct_nil.
+ simpl in H.
+ inversion H.
+ subst.
+ set (IHl1 _ H3) as H3'.
+ destruct H3'.
+ split; auto.
+ apply distinct_cons; auto.
+ intro.
+ apply H2.
+ apply In_both; auto.
+ Qed.
+
+Lemma mapOptionTree'_compose : forall T A B (t:Tree ??T) (f:T->??A)(g:A->??B),
+ mapOptionTree' g (mapOptionTree' f t)
+ =
+ mapOptionTree' (fun x => match f x with None => None | Some x => g x end) t.
+ intros; induction t.
+ destruct a; auto.
+ simpl.
+ destruct (f t); reflexivity.
+ simpl.
+ rewrite <- IHt1.
+ rewrite <- IHt2.
+ reflexivity.
+ Qed.
+
+Lemma strip_lemma a x t : stripOutVars (a::x) t = stripOutVars (a::nil) (stripOutVars x t).
+ unfold stripOutVars.
+ rewrite mapOptionTree'_compose.
+ simpl.
+ induction t.
+ destruct a0.
+ simpl.
+ induction x.
+ reflexivity.
+ simpl.
+ destruct (eqd_dec v a0).
+ destruct (eqd_dec v a); reflexivity.
+ apply IHx.
+ reflexivity.
+ simpl.
+ rewrite <- IHt1.
+ rewrite <- IHt2.
+ reflexivity.
+ Qed.
+
+Lemma strip_twice_lemma x y t : stripOutVars x (stripOutVars y t) = stripOutVars (app y x) t.
+(*
+ induction x.
+ simpl.
+ unfold stripOutVars.
+ simpl.
+ rewrite mapOptionTree'_compose.
+ induction t.
+ destruct a; try reflexivity.
+ simpl.
+ destruct (dropVar y v); reflexivity.
+ simpl.
+ rewrite IHt1.
+ rewrite IHt2.
+ reflexivity.
+ rewrite strip_lemma.
+ rewrite IHx.
+ rewrite <- strip_lemma.
+ rewrite app_comm_cons.
+ reflexivity.
+*)
+ admit.
+ Qed.
+
+Lemma strip_distinct a y : (not (In a (leaves y))) -> stripOutVars (a :: nil) y = y.
+ intros.
+ induction y.
+ destruct a0; try reflexivity.
+ simpl in *.
+ unfold stripOutVars.
+ simpl.
+ destruct (eqd_dec v a).
+ subst.
+ assert False.
+ apply H.
+ left; auto.
+ inversion H0.
+ auto.
+ rewrite <- IHy1 at 2.
+ rewrite <- IHy2 at 2.
+ reflexivity.
+ unfold not; intro.
+ apply H.
+ eapply In_both' in H0.
+ apply H0.
+ unfold not; intro.
+ apply H.
+ eapply In_both in H0.
+ apply H0.
+ Qed.
+
+Lemma drop_distinct x v : (not (In v x)) -> dropVar x v = Some v.
+ intros.
+ induction x.
+ reflexivity.
+ simpl.
+ destruct (eqd_dec v a).
+ subst.
+ assert False. apply H.
+ simpl; auto.
+ inversion H0.
+ apply IHx.
+ unfold not.
+ intro.
+ apply H.
+ simpl; auto.
+ Qed.
+
+Lemma in3 {T}(a b c:list T) q : In q (app a c) -> In q (app (app a b) c).
+ induction a; intros.
+ simpl.
+ simpl in H.
+ apply In_both'.
+ auto.
+ rewrite <- ass_app.
+ rewrite <- app_comm_cons.
+ simpl.
+ rewrite ass_app.
+ rewrite <- app_comm_cons in H.
+ inversion H.
+ left; auto.
+ right.
+ apply IHa.
+ apply H0.
+ Qed.
+
+Lemma distinct3 {T}(a b c:list T) : distinct (app (app a b) c) -> distinct (app a c).
+ induction a; intros.
+ simpl in *.
+ apply distinct_app in H; auto.
+ destruct H; auto.
+ rewrite <- app_comm_cons.
+ apply distinct_cons.
+ rewrite <- ass_app in H.
+ rewrite <- app_comm_cons in H.
+ inversion H.
+ subst.
+ intro q.
+ apply H2.
+ rewrite ass_app.
+ apply in3.
+ auto.
+ apply IHa.
+ rewrite <- ass_app.
+ rewrite <- ass_app in H.
+ rewrite <- app_comm_cons in H.
+ inversion H.
+ subst.
+ auto.
+ Qed.
+
+Lemma strip_distinct' y : forall x, distinct (app x (leaves y)) -> stripOutVars x y = y.
+ induction x; intros.
+ simpl in H.
+ unfold stripOutVars.
+ simpl.
+ induction y; try destruct a; auto.
+ simpl.
+ rewrite IHy1.
+ rewrite IHy2.
+ reflexivity.
+ simpl in H.
+ apply distinct_app in H; destruct H; auto.
+ apply distinct_app in H; destruct H; auto.
+ rewrite <- app_comm_cons in H.
+ inversion H; subst.
+ set (IHx H3) as qq.
+ rewrite strip_lemma.
+ rewrite IHx.
+ apply strip_distinct.
+ unfold not; intros.
+ apply H2.
+ apply In_both'.
+ auto.
+ auto.
+ Qed.
+
+Lemma updating_stripped_tree_is_inert'
+ {Γ} lev
+ (ξ:VV -> LeveledHaskType Γ ★)
+ lv tree2 :
+ mapOptionTree (update_ξ ξ lev lv) (stripOutVars (map (@fst _ _) lv) tree2)
+ = mapOptionTree ξ (stripOutVars (map (@fst _ _) lv) tree2).
+ induction tree2.
+ destruct a.
+ simpl.
+ induction lv.
+ reflexivity.
+ simpl.
+ destruct a.
+ simpl.
+ set (eqd_dec v v0) as q.
+ destruct q.
+ auto.
+ set (dropVar (map (@fst _ _) lv) v) as b in *.
+ destruct b.
+ inversion IHlv.
+ admit.
+ auto.
+ reflexivity.
+ simpl.
+ unfold stripOutVars in *.
+ rewrite <- IHtree2_1.
+ rewrite <- IHtree2_2.
+ reflexivity.
+ Qed.
+
+Lemma update_ξ_lemma `{EQD_VV:EqDecidable VV} : forall Γ ξ (lev:HaskLevel Γ)(varstypes:Tree ??(VV*_)),
+ distinct (map (@fst _ _) (leaves varstypes)) ->
+ mapOptionTree (update_ξ ξ lev (leaves varstypes)) (mapOptionTree (@fst _ _) varstypes) =
+ mapOptionTree (fun t => t@@ lev) (mapOptionTree (@snd _ _) varstypes).
+ admit.
+ Qed.
+
+
+
+