{-# LANGUAGE TypeOperators, MultiParamTypeClasses, TypeFamilies #-}-- | Abstracts the implementation details of a single-insertion, single-extraction queuelike structure.moduleData.Queue.Classwhere--import Data.Foldable(Foldable(..))importData.List(unfoldr)importData.MaybeimportqualifiedData.ListasFoldimportControl.Monad.Instances()importControl.Monad-- | Type that only orders on the key, ignoring the value completely; frequently useful in priority queues, so made available here.datae:->f=e:->finstanceEqf=>Eq(e:->f)where(_:->x)==(_:->y)=x==yinstanceOrdf=>Ord(e:->f)where(_:->x)`compare`(_:->y)=comparexy-- | A generic type class encapsulating a generic queuelike structure, that supports single-insertion and single-extraction; this abstraction includes priority queues, stacks, and FIFO queues. There are many minimal implementations, so each method lists the prerequisites for its default implementation. Most implementations will implement 'empty', ('singleton' and 'merge') or 'insert', ('peek' and 'delete') or 'extract', and 'size'. (The absolute minimal implementation is 'empty', 'insert', 'extract', and 'size'.)classIQueueqwheretypeQueueKeyq-- | Inserts a single element into the queue. The default implementation uses 'merge' and 'singleton'.insert::QueueKeyq->q->qinsertxq=q`merge`singletonx-- | Inserts several elements into the queue. The default implementation uses 'insert'. (In some cases, it may be advantageous to override this implementation with @xs \``insertAll`\` q = q \``merge`\` `fromList` xs@.){-# INLINE insertAll #-}insertAll::[QueueKeyq]->q->qinsertAll=flip(foldrinsert)-- | Attempts to extract an element from the queue; if the queue is empty, returns Nothing. The default implementation uses 'peek' and 'delete'.extract::q->Maybe(QueueKeyq,q)extract=liftM2(liftM2(,))topdelete-- | Gets the element that will next be extracted from the queue, if there is an element available. The default implementation uses 'extract'.top::q->Maybe(QueueKeyq)top=liftMfst.extract-- | Deletes an element from the queue, if the queue is nonempty. The default implementation uses 'extract'.delete::q->Maybeqdelete=liftMsnd.extract-- | Constructs an empty queue. The default implementation uses 'fromList'.empty::qempty=fromList[]-- | Constructs a queue with a single element. The default implementation uses 'insert' and 'empty'.singleton::QueueKeyq->qsingletonx=insertxempty-- | Constructs a queue with all of the elements in the list. The default implementation uses 'insertAll' and 'empty'.{-# INLINE fromList #-}fromList::[QueueKeyq]->qfromListxs=insertAllxsempty-- | Gets the size of the queue. The default implementation uses 'toList_'.size::q->Intsize=length.toList_-- | Checks if the queue is empty. The default implementation uses 'peek'.null::q->Boolnull=isNothing.top-- | Extracts every element from the queue. The default implementation uses 'extract'.toList::q->[QueueKeyq]toList=unfoldrextract-- | Extracts every element from the queue, with no guarantees upon order. The default implementation uses 'toList'.toList_::q->[QueueKeyq]toList_=toList-- | Merges two queues so that the contents of the second queue are inserted into the first queue in extraction order. The default implementation uses 'toList' and 'insertAll'.{-# INLINE merge #-}merge::q->q->qq1`merge`q2=insertAll(toListq2)q1mergeAll::[q]->qmergeAll=foldrmergeempty