Notation "a # b <- c" := (set _ a b c) (at level 1, b at next level).Definition pred_opt (x: option A) (y: option B) :=
  match x with
  | None => true
  | Some z => pred z y
  end.Fixpoint map_forall2 (m1: map A) (m2: map B) {struct m1}: bool :=
  match m1, m2 with
  | Leaf, _ => true
  | Node l1 o1 r1, Leaf =>
      map_forall2 l1 (Leaf B) && pred_opt o1 None && map_forall2 r1 (Leaf B)
  | Node l1 o1 r1, Node l2 o2 r2 =>
      map_forall2 l1 l2 && pred_opt o1 o2 && map_forall2 r1 r2
  end.Fixpoint map_forall2' (m1: map A) (m2: map B) {struct m2}: bool :=
  match m1, m2 with
  | Leaf, _ => true
  | Node l1 o1 r1, Leaf =>
      map_forall2 l1 (Leaf B) && pred_opt o1 None && map_forall2 r1 (Leaf B)
  | Node l1 o1 r1, Node l2 o2 r2 =>
      map_forall2' l1 l2 && pred_opt o1 o2 && map_forall2' r1 r2
  end.

(* Specifications: *)
Lemma map_forall2_eq : forall (m1:map A) (m2:map B), map_forall2 m1 m2 = map_forall2' m1 m2.
Lemma map_forall2_correct: forall m1 m2 i x, map_forall2 m1 m2 = true -> m1#i = Some x -> pred x m2#i = true.
Lemma map_forall2_complete: forall m1 m2, (forall i x, m1#i = Some x -> pred x m2#i = true) -> map_forall2 m1 m2 = true.
Lemma map_forall2_eq : forall (m1:map A) (m2:map B), map_forall2 m1 m2 = map_forall2' m1 m2.
Lemma map_forall2_correct: forall m1 m2 i x, map_forall2 m1 m2 = true -> m1#i = Some x -> pred x m2#i = true.
Lemma map_forall2_complete: forall m1 m2, (forall i x, m1#i = Some x -> pred x m2#i = true) -> map_forall2 m1 m2 = true.
Lemma map_forall2_eq : forall (m1:map A) (m2:map B), map_forall2 m1 m2 = map_forall2' m1 m2.
Lemma map_forall2_correct: forall m1 m2 i x, map_forall2 m1 m2 = true -> m1#i = Some x -> pred x m2#i = true.
Lemma map_forall2_complete: forall m1 m2, (forall i x, m1#i = Some x -> pred x m2#i = true) -> map_forall2 m1 m2 = true.