module Data.Queue.QueueHelpers (HeapQ(..), endoMaybe, order, fusing) where
import Data.Monoid
data HeapQ m = HQ {elts :: !Int, heap :: Maybe m}
instance Monoid m => Monoid (HeapQ m) where
mempty = HQ 0 mempty
HQ n1 h1 `mappend` HQ n2 h2 = HQ (n1 + n2) (h1 `mappend` h2)
mconcat qs = uncurry HQ $ fuseMerge [(n, h) | HQ n h <- qs]
endoMaybe :: (a -> a -> a) -> Maybe a -> Maybe a -> Maybe a
endoMaybe f (Just a) (Just b) = Just (f a b)
endoMaybe _ ma Nothing = ma
endoMaybe _ _ mb = mb
fusing :: Monoid m => [m] -> Maybe m
fusing [] = Nothing
fusing [t] = Just t
fusing ts = fusing (fuse mappend ts) where
fuse !f (t1:t2:ts) = (t1 `f` t2):fuse f ts
fuse _ ts = ts
order :: (e -> e -> Ordering) -> e -> e -> (e, e)
order cmp x y | cmp x y == GT = (y, x)
| otherwise = (x, y)
data IntAcc e = IA !Int e
fuseMerge :: Monoid m => [(Int, Maybe m)] -> (Int, Maybe m)
fuseMerge qs = let IA n ts = foldr merger (IA 0 []) qs in (n, fusing ts) where
merger (m, mt) (IA n ts) = case mt of
Nothing -> IA n ts
Just t -> IA (n+m) (t:ts)