(* This auxiliary tactic simplifies expressions of the form [x + 0] in the goal. It does *not* affect [x + ?y] where [y] is a meta-variable. *)
Ltac plus_0_r :=
repeat match goal with |- context[?x + 0] => rewrite (plus_0_r x) end.
Ltac plus_0_r_in h :=
repeat match type of h with context[?x + 0] => rewrite (plus_0_r x) in h end.
(* It is worth noting that instead of writing: traverse (fun l x => var (lift w (l + k) x)) 0 t one might have instead written: traverse (fun l x => var (lift w l x)) k t Indeed, because [traverse] is relative, these two expressions are equivalent. The following lemma states this fact. When used as a rewriting rule, it recognizes a general form of the above expressions and replaces it with an application of [lift]. *)

(* Specifications: *)
Lemma recognize_lift:
forall `{Var V, Traverse V T},
TraverseRelative ->
forall w k1 k2 t,
forall traverse_,
traverse_ = traverse -> (* helps rewrite *)
traverse_ (fun l x => var (lift w (l + k2) x)) k1 t =
lift w (k1 + k2) t.