-- | Simple Functional queues based on a double list. This usually achieves good amortized bounds
module Data.Queue (
-- * Types
Queue,
-- * Functions
empty,
isEmpty,
push,
pop,
Data.Queue.filter)
where
import qualified Data.List as Lst
data Queue a = Queue [a] [a]
-- | The definition of an empty Queue
empty :: Queue a
empty = Queue [] []
-- | Returns True on an empty Queue, and False otherwise.
isEmpty :: Queue a -> Bool
isEmpty (Queue [] []) = True
isEmpty _ = False
-- | Pushes a new element to the tail of the list.
-- Operates in constant time.
push :: a -> Queue a -> Queue a
push e (Queue front back) = Queue front (e : back)
-- | Pops the top most element off the queue.
-- Operates in amortized constant time
pop :: Queue a -> Maybe (a, Queue a)
pop (Queue [] []) = Nothing
pop (Queue (e : es) back) = Just (e, Queue es back)
pop (Queue [] back) = pop (Queue (reverse back) [])
-- | Generates a new Queue only containing elements for which
-- p returns true.
filter :: (a -> Bool) -> Queue a -> Queue a
filter p (Queue front back) = Queue (Lst.filter p front) (Lst.filter p back)