Proof with auto.
pattern x, y.
apply two_lists_rect.
intros.
rewrite merges_real_eq in H1.
simpl in H1.
intuition.
subst.
apply (filter_none p x0)...
intros.
rewrite merges_nil_r in H1.
simpl in H1.
intuition.
subst.
apply filter_all...
intros.
rewrite merges_real_eq in H3.
rewrite map_app in H3.
repeat rewrite map_map in H3.
apply in_app_or in H3.
simpl in H3.
destruct H3.
rewrite H1 in H3.
Focus 2. left...
rewrite <- (map_map (filter p) (cons x0)) in H3.
apply in_map_iff in H3.
destruct H3.
destruct H3.
subst.
f_equal.
apply H...
intuition.
rewrite H2 in H3.
Focus 2. left...
apply H0...
intuition.
Qed.
(* While a closed formula for merges length is tricky, we can easily prove that the length depends only on the length of the arguments. *)
Instance length_merges_mor: Proper (on length eq ==> on length eq ==> on length eq) merges.
Proof with auto.
unfold on.
do 4 intro.
generalize y H. clear y H.
unfold merges at 1.
destruct merges_ex.
simpl in *.
induction m; intros.
destruct y...
discriminate.
destruct y0.
rewrite merges_nil_r...
discriminate.
destruct y0. discriminate.
destruct y1. discriminate.
inversion H.
inversion H0.
rewrite merges_real_eq.
repeat rewrite app_length.
repeat rewrite map_length...
Qed.

(* Specifications: *)
Lemma merges_ne_nil x y: merges x y <> nil.
Proof with try discriminate; auto.