(* Attempting to rewrite in both directions may seem redundant, because of the
   symmetry of the law [insert_insert]. It is not: because [omega] fails in
   the presence of meta-variables, rewriting in one direction may be possible
   while the other direction fails. *)

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

(* Specifications: *)
Lemma insert_insert_always: forall A k s (a b : option A) e, raw_insert k a (raw_insert s b e) = raw_insert (shift k s) b (raw_insert (if le_gt_dec k s then k else k - 1) a e).
Lemma insert_nil: forall A x a (e : env A), insert x a e = nil -> False.
Lemma insert_eq_insert_1: forall A x a1 a2 (e1 e2 : env A), insert x a1 e1 = insert x a2 e2 -> a1 = a2.
Lemma insert_eq_insert_2: forall A x a1 a2 (e1 e2 : env A), insert x a1 e1 = insert x a2 e2 -> forall b, insert x b e1 = insert x b e2.
Lemma insert_eq_insert_3: forall A x1 x2 a1 a2 (e1 e2 : env A), insert x1 a1 e1 = insert x2 a2 e2 -> x1 <> x2 -> exists e y1 y2, e1 = insert y1 a2 e /\ e2 = insert y2 a1 e /\ shift x1 y1 = x2 /\ y2 = (if le_gt_dec x1 y1 then x1 else x1 - 1).