(* this horrible first argument to repeat is inconsequential. what matters is that we express perms (filter p l) in terms of map (filter p) (perms l) *)
Proof with auto.
intros.
rewrite (complementary_filter_perm p l) at 1.
rewrite perms_app.
rewrite map_concat_map.
unfold product.
rewrite concatMap_concatMap'.
apply Permutation_concatMap.
intros.
unfold Basics.compose.
rewrite map_map.
unfold uncurry.
simpl.
set (t := repeat (length (merges x (filter (fun q => negb (p q)) l))) x).
rewrite (@map_repeat _ _ (fun x0 : list T => map (filter p) (merges x x0)) t (perms (filter (fun x0 : T => negb (p x0)) l))).
rewrite length_perms.
subst t.
rewrite concat_repeat.
pose proof (Permutation_length (perms_are_perms _ _ H)).
rewrite (length_merges_mor H0 refl_equal)...
intros.
rewrite (@map_repeat _ _ (filter p) x (merges x x0)).
subst t.
pose proof (Permutation_length (perms_are_perms _ _ H0)).
rewrite (length_merges_mor refl_equal H1)...
intros.
apply (filter_merges) with p x0...
intros.
apply (filter_In p z l)...
apply Permutation_in with x...
apply perms_are_perms...
intros.
pose proof (Permutation_in _ (perms_are_perms _ _ H0) H2).
cut (negb (p z) = true).
intros.
destruct (p z)...
apply (filter_In (fun q => negb (p q)) z l)...
Qed.
Instance Permutation_length_morphism T: Proper (Permutation ==> eq) (@length T) :=
@Permutation_length T.

(* Specifications: *)
Lemma repeat_map_comm A B (f: A -> B) n: ext_eq (map f ∘ repeat n) (repeat n ∘ f).
Proof with auto.