-----------------------------------------------------------------------------
-- |
-- Module      :  Control.Monad.Queue.Class
-- Copyright   :  (c) Leon P Smith 2009
-- License     :  BSD3
--
-- Maintainer  :  leon at melding-monads dot com
-- Stability   :  experimental
-- Portability :  portable
--
-----------------------------------------------------------------------------

{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE FunctionalDependencies     #-}

module Control.Monad.Queue.Class where

import Control.Monad.Queue.Util

class Monad q => MonadQueue e q | q -> e where
  -- | Enqueue an element to a queue
  enQ     :: e -> q ()
  -- | Dequeue an element,  returns 'Nothing' if the queue is empty.
  deQ     :: q (Maybe e)
  -- | Dequeue up to @maxlen@ elements.
  deQs    :: Integral maxlen => maxlen -> q [e]
  -- | Examines the front element of the queue without removing it.
  peekQ   :: q (Maybe e)
  -- | Examines up to @maxlen@ elements of the queue without removing them.
  peekQs  :: Integral maxlen  => maxlen -> q [e]
  -- | Examines the element currently at position @index@,  indexing starts at @0@.
  peekQn  :: Integral index   => index  -> q (Maybe e)
  -- | Returns the current length of the queue
  lenQ    :: Integral len => q len

  deQ = do
          es <- deQs (1 :: LenType)
          case es of
           []    -> return Nothing
           (e:_) -> return (Just e)

  deQs n
     | n <= 0    = return []
     | otherwise = deQ >>=  maybe (return [])
                            (\e ->  do
                                    es <- deQs (n-1)
                                    return (e:es))