Ltac map_insert :=
  first [
    rewrite map_insert; reflexivity
  | rewrite <- map_insert; reflexivity
  ].

(* Specifications: *)
Lemma map_insert_eq: forall A B (f : A -> B) x a b e, f a = b -> map f (insert x a e) = insert x b (map f e).
Lemma map_raw_insert: forall A B (f : A -> B) x e, map f (raw_insert x None e) = raw_insert x None (map f e).
Lemma map_map_fuse: forall A B C (f : B -> C) (g : A -> B) h e, (forall (d : A), f (g d) = h d) -> map f (map g e) = map h e.
Lemma map_map_exchange: forall A F G B (f1 : F -> B) (f2 : A -> F) (g1 : G -> B) (g2 : A -> G) e, (forall (d : A), f1 (f2 d) = g1 (g2 d)) -> map f1 (map f2 e) = map g1 (map g2 e).
Lemma map_lift_map_lift: forall T k s wk ws (e : env T), forall `{Lift T}, @LiftLift T _ -> k <= s -> map (lift wk k) (map (lift ws s) e) = map (lift ws (wk + s)) (map (lift wk k) e).
Lemma map_insert_map: forall A (f g h : A -> A) x (a : A) e, (forall a, f (g a) = g (h a)) -> map f (insert x a (map g e)) = insert x (f a) (map g (map h e)).
Lemma map_map_vanish: forall A B (f : B -> A) (g : A -> B) (e : env A), (forall x, f (g x) = x) -> map f (map g e) = e.
Lemma fold_empty: forall A B (f : option A -> B -> B) accu, fold f (@empty _) accu = accu.
Lemma fold_insert: forall A B (f : option A -> B -> B) o e accu, fold f (raw_insert 0 o e) accu = f o (fold f e accu).
Lemma fold_invariant: forall A B (P : env A -> B -> Prop) f accu, P (@empty _) accu -> (forall o e accu, P e accu -> P (raw_insert 0 o e) (f o accu)) -> forall e, P e (fold f e accu).
Lemma length_monotonic: forall A (e : env A) k1 k2, length e <= k1 -> k1 <= k2 -> length e <= k2.
Lemma lookup_beyond_length: forall A (e : env A) x, length e <= x -> lookup x e = None.
Lemma defined_implies_below_length: forall A (e : env A) x k a, length e <= k -> lookup x e = Some a -> x < k.
Lemma length_empty: forall A k, length (@empty A) <= k.