The association list here is actually a "red herring". This is really a more general question of how to do a merge using a function to combine terms with equal keys. The association list version is the same question, but with a pre-applied Schwartzian transform.

Stated this way, we want a function with this type:

mergeCombineWith :: (a -> a -> Ordering) -> (a -> a -> a) -> [a] -> [a] -> [a]

where the first parameter defines the ordering and the second parameter is the combining function to be applied to elements with equal keys. We assume that the input lists are pre-sorted. If we also assume that neither of the input lists has any duplicate keys, or that we also want to combine duplicates within the same input list, then the solution is simple. Given a traditional merge function, of type:

mergeWith :: (a -> a -> Ordering) -> [a] -> [a] -> [a]

then our desired function is obtained by grouping the results of the traditional merge:

mergeCombineWith cmp comb xs ys = map combs . groupBy eq $ mergeWith cmp xs ys where combs = foldr1 comb eq x y = isEQ $ cmp x y isEQ EQ = True isEQ _ = False

More generally, it would be interesting to consider merging many lists, not just two. That could be done in a straightforward way using a fold:

multiMergeCombineWith :: (a -> a -> Ordering) -> (a -> a -> a) -> [[a]] -> [a] multiMergeCombineWith cmp comb = foldr1 $ mergeCombineWith cmp comb

But that solution would be inefficient if there are many lists to combine. A better way would be to put the lists into a priority queue and always examine first the lists whose first elements are smallest in the given ordering. There are several good priority queue implementations on Hackage.

However, once again, if you have a solution to the multi-list problem for a traditional merge, you don't need to re-invent the wheel. First do the traditional merge, then group and combine, as above.

Thanks to Daniel Wagner for pointing out to me that versions of the two traditional merge functions can be found in the data-ordlist package on Hackage, called there mergeBy and mergeAllBy.

EDIT: A new priority queue implementation was recently published on Hackage.See the discussion about it in this reddit thread.