-----------------------------------------------------------------------------
-- |
-- 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