packages feed

control-monad-queue-0.0.9: Control/Monad/Queue/ST.hs

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

{-# LANGUAGE RankNTypes #-}

module Control.Monad.Queue.ST
     ( Q()
     , enQ
     , deQ
     , lenQ_
     , runResult
     ) where

import qualified Control.Monad.Queue.Class
import Control.Monad.Queue.Util
import Control.Monad.ST.Strict
import Data.STRef.Strict

type  ListPtr st a = STRef st (List st a)
data  List st a
   =  Null
   |  Cons a {-# UNPACK #-} !(ListPtr st a)

type  QSt st res elt = LenType -> ListPtr st elt -> ListPtr st elt -> ST st res
newtype Q elt a
      = Q { unQ :: forall res st. ((a -> QSt st res elt) -> QSt st res elt) }

instance Monad (Q st) where
    return a = Q (\k -> k a)
    m >>= f  = Q (\k -> unQ m (\a -> unQ (f a) k))

enQ :: e -> Q e ()
enQ e  = Q $ \k n a z -> do
                 z' <- newSTRef Null
                 writeSTRef z (Cons e z')
                 (k () $! n+1) a z'

deQ :: Q e (Maybe e)
deQ    = Q $ \k n a z -> do
                 list <- readSTRef a
                 case list of
                   Null
                     -> (k Nothing  $! n-1) a  z
                   (Cons e a')
                     -> (k (Just e) $! n-1) a' z

lenQ_ :: Q e LenType
lenQ_ = Q (\k n a z -> k n n a z)

runResult m = runST $ do
  ref <- newSTRef Null
  unQ m (\a n front back -> return a) 0 ref ref