packages feed

pqueue-mtl-1.0.4: Data/Queue/PQueue.hs

{-# LANGUAGE NamedFieldPuns, TypeSynonymInstances, FlexibleInstances, TypeFamilies, GeneralizedNewtypeDeriving #-}
{-# OPTIONS -fno-warn-missing-methods -fno-warn-name-shadowing #-}
{- | An efficient implementation of a priority queue.

The implementation of 'PQueue' is based on a /pairing heap/, a simple and efficient implementation of a general-purpose priority queue.  'PQueue' supports 'insert', 'merge', and 'peek' in constant time, and 'extract' and 'delete' in logarithmic time.
-}

module Data.Queue.PQueue (PQueue) where

import Data.Queue.Class
import Data.Queue.QueueHelpers

import Data.Maybe
import Data.Monoid

import Control.Monad

data Tree e = T e [Tree e]
newtype PQueue e = PQ (HeapQ (Tree e)) deriving (Monoid, Queuelike)

single :: e -> HeapQ (Tree e)
single x = HQ 1 $ Just (T x [])

instance Ord e => Monoid (Tree e) where
	-- no actual mzero instance, but induces a correct Monoid instance for Heap e
	t1@(T x1 ts1) `mappend` t2@(T x2 ts2) 
		| x1 <= x2	= T x1 (t2:ts1)
		| otherwise	= T x2 (t1:ts2)

instance Ord e => Queuelike (HeapQ (Tree e)) where
	{-# INLINE fromList #-}
	{-# INLINE toList_ #-}
	{-# INLINE mergeAll #-}
	{-# INLINE insertAll #-}

	type QueueKey (HeapQ (Tree e)) = e

	empty = mempty
	singleton = single
	fromList ts = mconcat (map single ts)

	x `insert` q = q `mappend` single x
	xs `insertAll` q = q `mappend` fromList xs
	merge = mappend
	mergeAll = mconcat
	
	extract (HQ n t) = fmap (\ (T x ts) ->  (x, HQ (n-1) (fusing ts))) t
	toList_ = maybe [] flatten . heap
	size = elts

flatten :: Tree e -> [e]
flatten (T x ts) = [x] ++ concatMap flatten ts