Definition me (ab: list T * list T): nat := length (fst ab) + length (snd ab).Program Fixpoint merges_ex (ab: list T * list T) {measure (me ab)}: sig (merges_spec (fst ab) (snd ab)) :=
    match ab with
    | (nil, x) => x :: nil
    | (x, nil) => x :: nil
    | (x :: y, h :: t) => map (cons x) (merges_ex (y, h :: t)) ++ map (cons h) (merges_ex (x :: y, t))
    end.Definition merges (a b: list T): list (list T) := proj1_sig (merges_ex (a, b)).

(* Specifications: *)
Lemma merges_real_eq a b: merges a b = match a, b with | nil, x => x :: nil | x, nil => x :: nil | x :: y, h :: t => map (cons x) (merges y (h :: t)) ++ map (cons h) (merges (x :: y) t) end.
Lemma product_app: forall T (a b c: list T), product (a ++ b) c = product a c ++ product b c.
Lemma product_concat: forall T (a: list (list T)) (b: list T), product (concat a) b = concat (map (flip (@product _ _) b) a).
Lemma concatMap_insert_everywhere_comm x y l: Permutation (concat (map (insert_everywhere x) (insert_everywhere y l))) (concat (map (insert_everywhere y) (insert_everywhere x l))).
Lemma merges_insert_everywhere a l: insert_everywhere a l = merges (a :: nil) l.
Lemma merges_insert_everywhere' a l: Permutation (insert_everywhere a l) (merges l (a :: nil)).
Lemma insert_everywhere_merges_commute a x y: Permutation (concat (map (insert_everywhere a) (merges y x))) (concat (map (merges y) (insert_everywhere a x))).
Lemma merges_sym x y: Permutation (merges x y) (merges y x).
Lemma perms_app (a b: list T): Permutation (perms (a ++ b)) (concat (map (uncurry merges) (product (perms a) (perms b)))).
Lemma filter_merges p (x y: list T): (forall z, In z x -> p z = true) -> (forall z, In z y -> p z = false) -> forall r, In r (map (filter p) (merges x y)) -> r = x.
Lemma merges_ne_nil x y: merges x y <> nil.
Lemma map_repeat A B (f: A -> B) c (l: list A): (forall x, In x l -> f x = c) -> map f l = repeat (length l) c.
Lemma repeat_plus T (c: T) n m: repeat (n + m) c = repeat n c ++ repeat m c.
Lemma concat_repeat T n m (c: T): concat (repeat n (repeat m c)) = repeat (n * m) c.
Lemma length_repeat T (c: T) n: length (repeat n c) = n.
Lemma concat_nil X (l: list (list X)): (forall x, In x l -> x = nil) -> concat l = nil.
Lemma empty_nil X (x: list X): length x = 0%nat -> x = nil.
Lemma Permuted_Permutation_map T U (R: relation T) (f: T -> U): (forall x y, R x y -> f x = f y) -> forall a b, Permuted R a b -> Permutation (map f a) (map f b).
Lemma elemsR_length A (R: A -> A -> Prop) a b (H: elemsR R a b): length a = length b.
Lemma elemsRimpl A B (R: A -> B -> Prop) (l: list A): (forall x, In x l -> sig (R x)) -> sig (elemsR R l).
Lemma elemsRuniq A B (R: A -> B -> Prop) (l: list A): (forall x, In x l -> forall y, R x y -> forall y', R x y' -> y = y') -> forall r, elemsR R l r -> forall r', elemsR R l r' -> r = r'.