It seems quite amenable to a recursive implementation:
mergeQueues :: Queue a -> Queue a -> Queue a
mergeQueues qa qb =
merge qa qb emptyQueue
where
merge qa qb qr
| isEmpty qa = append qb qr
| otherwise = move (merge qb) qa qr
append q qr
| isEmpty q = qr
| otherwise = move append q qr
move f q qr =
let (val,q') = pop q
in f q' (push val qr)
Note that we just flip the queues back and forth as we recurse in order to alternate between them, until one is empty, at which point we just append from the one to the other.
Note that, though this is longer than the imperative version given by ribond, this does a minimal number of isEmpty
checks. If you don't mind doing as many checks as his does in a slightly more optimized version (assiging the isEmpty values to variables for re-use below), you can remove the append
function and just keep calling merge
instead, after adding an initial test to merge
that tests for both queues being empty and terminating the recursion if so.
For those not familiar with Haskell, we pass in to move the next function to call (this is higher-order functional programming); in the append
case, that's just append, in the move
case that's a "partially applied" move function: it gets the first parameter, qb
applied before we call move
, and then move
applies the other two parameters.
This sounds like a reasonable task one might encounter in day-to-day business programming. However, if this is a homework function, I suggest you study carefully how the above code works, and I think you'll learn something.
Also, there's a possibility that there's an error in the above code; proving that it works (or finding the bug) would be an excellent exercise.