{-# LANGUAGE ConstraintKinds   #-}
{-# LANGUAGE FlexibleContexts  #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies      #-}
-- | Various typeclasses for mutable containers.
module Data.Mutable.Class
    ( PrimMonad
    , PrimState
    , RealWorld
    , MutableQueue
    , MutableStack
    , MutableDeque
    , IORef
    , asIORef
    , STRef
    , asSTRef
    , MutVar
    , asMutVar
    , MutableContainer (..)
    , MutableRef (..)
    , MutableAtomicRef (..)
    , MutableCollection (..)
    , MutablePushFront (..)
    , MutablePushBack (..)
    , MutablePopFront (..)
    , MutablePopBack (..)
    , pushFrontRef
    , pushBackRef
    , popFrontRef
    , popBackRef
    ) where

import           Control.Monad.Primitive
import           Data.IORef
import           Data.Monoid
import           Data.MonoTraversable    (Element)
import           Data.Primitive.MutVar
import qualified Data.Sequences          as Seqs
import           Data.STRef

-- | The parent typeclass for all mutable containers.
--
-- Since 0.2.0
class MutableContainer c where
    -- | Associated type giving the primitive state token for the given
    -- container, much like 'PrimState' from primitive.
    --
    -- Since 0.2.0
    type MCState c

instance MutableContainer (IORef a) where
    type MCState (IORef a) = PrimState IO
instance MutableContainer (STRef s a) where
    type MCState (STRef s a) = s
instance MutableContainer (MutVar s a) where
    type MCState (MutVar s a) = s

-- | Typeclass for single-cell mutable references.
--
-- Since 0.2.0
class MutableContainer c => MutableRef c where
    -- | Associated type giving the type of the value inside the mutable
    -- reference.
    --
    -- Since 0.2.0
    type RefElement c

    -- | Create a new mutable reference with the given value.
    --
    -- Since 0.2.0
    newRef :: (PrimMonad m, PrimState m ~ MCState c)
           => RefElement c
           -> m c

    -- | Read the current value in the mutable reference.
    --
    -- Since 0.2.0
    readRef :: (PrimMonad m, PrimState m ~ MCState c)
            => c
            -> m (RefElement c)

    -- | Write a new value to the mutable reference.
    --
    -- Since 0.2.0
    writeRef :: (PrimMonad m, PrimState m ~ MCState c)
             => c
             -> RefElement c
             -> m ()

    -- | Modify the value in the mutable reference, without necessarily forcing the result.
    --
    -- Note: some implementations /will/ force the result, in particular
    -- @PRef@, @SRef@, and @URef@.
    --
    -- Since 0.2.0
    modifyRef :: (PrimMonad m, PrimState m ~ MCState c)
              => c
              -> (RefElement c -> RefElement c)
              -> m ()

    -- | Modify the value in the mutable reference, forcing the result.
    --
    -- Since 0.2.0
    modifyRef' :: (PrimMonad m, PrimState m ~ MCState c)
               => c
               -> (RefElement c -> RefElement c)
               -> m ()

instance MutableRef (IORef a) where
    type RefElement (IORef a) = a
    newRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
RefElement (IORef a) -> m (IORef a)
newRef = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. a -> IO (IORef a)
newIORef
    {-# INLINE newRef #-}
    readRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> m (RefElement (IORef a))
readRef = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IORef a -> IO a
readIORef
    {-# INLINE readRef #-}
    writeRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> RefElement (IORef a) -> m ()
writeRef IORef a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IORef a -> a -> IO ()
writeIORef IORef a
c
    {-# INLINE writeRef #-}
    modifyRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> (RefElement (IORef a) -> RefElement (IORef a)) -> m ()
modifyRef IORef a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef a
c
    {-# INLINE modifyRef #-}
    modifyRef' :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> (RefElement (IORef a) -> RefElement (IORef a)) -> m ()
modifyRef' IORef a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a. IORef a -> (a -> a) -> IO ()
modifyIORef' IORef a
c
    {-# INLINE modifyRef' #-}
instance MutableRef (STRef s a) where
    type RefElement (STRef s a) = a
    newRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
RefElement (STRef s a) -> m (STRef s a)
newRef = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a s. a -> ST s (STRef s a)
newSTRef
    {-# INLINE newRef #-}
    readRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a -> m (RefElement (STRef s a))
readRef = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. STRef s a -> ST s a
readSTRef
    {-# INLINE readRef #-}
    writeRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a -> RefElement (STRef s a) -> m ()
writeRef STRef s a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. STRef s a -> a -> ST s ()
writeSTRef STRef s a
c
    {-# INLINE writeRef #-}
    modifyRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a
-> (RefElement (STRef s a) -> RefElement (STRef s a)) -> m ()
modifyRef STRef s a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. STRef s a -> (a -> a) -> ST s ()
modifySTRef STRef s a
c
    {-# INLINE modifyRef #-}
    modifyRef' :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a
-> (RefElement (STRef s a) -> RefElement (STRef s a)) -> m ()
modifyRef' STRef s a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall s a. STRef s a -> (a -> a) -> ST s ()
modifySTRef' STRef s a
c
    {-# INLINE modifyRef' #-}
instance MutableRef (MutVar s a) where
    type RefElement (MutVar s a) = a
    newRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
RefElement (MutVar s a) -> m (MutVar s a)
newRef = forall (m :: * -> *) a.
PrimMonad m =>
a -> m (MutVar (PrimState m) a)
newMutVar
    {-# INLINE newRef #-}
    readRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a -> m (RefElement (MutVar s a))
readRef = forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> m a
readMutVar
    {-# INLINE readRef #-}
    writeRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a -> RefElement (MutVar s a) -> m ()
writeRef = forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> a -> m ()
writeMutVar
    {-# INLINE writeRef #-}
    modifyRef :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a
-> (RefElement (MutVar s a) -> RefElement (MutVar s a)) -> m ()
modifyRef = forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> (a -> a) -> m ()
modifyMutVar
    {-# INLINE modifyRef #-}
    modifyRef' :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a
-> (RefElement (MutVar s a) -> RefElement (MutVar s a)) -> m ()
modifyRef' = forall (m :: * -> *) a.
PrimMonad m =>
MutVar (PrimState m) a -> (a -> a) -> m ()
modifyMutVar'
    {-# INLINE modifyRef' #-}

-- | @MutableRef@s that provide for atomic modifications of their contents.
--
-- Since 0.2.0
class MutableRef c => MutableAtomicRef c where
    -- | Modify the value without necessarily forcing the result.
    --
    -- Since 0.2.0
    atomicModifyRef
        :: (PrimMonad m, PrimState m ~ MCState c)
        => c
        -> (RefElement c -> (RefElement c, a))
        -> m a

    -- | Modify the value, forcing the result.
    --
    -- Since 0.2.0
    atomicModifyRef'
        :: (PrimMonad m, PrimState m ~ MCState c)
        => c
        -> (RefElement c -> (RefElement c, a))
        -> m a
instance MutableAtomicRef (IORef a) where
    atomicModifyRef :: forall (m :: * -> *) a.
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a
-> (RefElement (IORef a) -> (RefElement (IORef a), a)) -> m a
atomicModifyRef IORef a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef IORef a
c
    {-# INLINE atomicModifyRef #-}
    atomicModifyRef' :: forall (m :: * -> *) a.
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a
-> (RefElement (IORef a) -> (RefElement (IORef a), a)) -> m a
atomicModifyRef' IORef a
c = forall (m1 :: * -> *) (m2 :: * -> *) a.
(PrimBase m1, PrimMonad m2, PrimState m1 ~ PrimState m2) =>
m1 a -> m2 a
primToPrim forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. IORef a -> (a -> (a, b)) -> IO b
atomicModifyIORef' IORef a
c
    {-# INLINE atomicModifyRef' #-}
instance MutableAtomicRef (MutVar s a) where
    atomicModifyRef :: forall (m :: * -> *) a.
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a
-> (RefElement (MutVar s a) -> (RefElement (MutVar s a), a)) -> m a
atomicModifyRef = forall (m :: * -> *) a b.
PrimMonad m =>
MutVar (PrimState m) a -> (a -> (a, b)) -> m b
atomicModifyMutVar
    {-# INLINE atomicModifyRef #-}
    atomicModifyRef' :: forall (m :: * -> *) a.
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a
-> (RefElement (MutVar s a) -> (RefElement (MutVar s a), a)) -> m a
atomicModifyRef' = forall (m :: * -> *) a b.
PrimMonad m =>
MutVar (PrimState m) a -> (a -> (a, b)) -> m b
atomicModifyMutVar'
    {-# INLINE atomicModifyRef' #-}

-- | Containers which contain 0 or more values.
--
-- Since 0.2.0
class MutableContainer c => MutableCollection c where
    -- | The type of each value in the collection.
    --
    -- Since 0.2.0
    type CollElement c

    -- | Create a new, empty collection.
    --
    -- Since 0.2.0
    newColl :: (PrimMonad m, PrimState m ~ MCState c)
            => m c
instance Data.Monoid.Monoid w => MutableCollection (IORef w) where
    type CollElement (IORef w) = Element w
    newColl :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef w)) =>
m (IORef w)
newColl = forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
RefElement c -> m c
newRef forall a. Monoid a => a
mempty
    {-# INLINE newColl #-}
instance Monoid w => MutableCollection (STRef s w) where
    type CollElement (STRef s w) = Element w
    newColl :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s w)) =>
m (STRef s w)
newColl = forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
RefElement c -> m c
newRef forall a. Monoid a => a
mempty
    {-# INLINE newColl #-}
instance Monoid w => MutableCollection (MutVar s w) where
    type CollElement (MutVar s w) = Element w
    newColl :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s w)) =>
m (MutVar s w)
newColl = forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
RefElement c -> m c
newRef forall a. Monoid a => a
mempty
    {-# INLINE newColl #-}

-- | Take a value from the front of the collection, if available.
--
-- Since 0.2.0
class MutableCollection c => MutablePopFront c where
    -- | Take a value from the front of the collection, if available.
    --
    -- Since 0.2.0
    popFront :: (PrimMonad m, PrimState m ~ MCState c)
             => c
             -> m (Maybe (CollElement c))
popFrontRef
    :: ( PrimMonad m
       , PrimState m ~ MCState c
       , MutableRef c
       , CollElement c ~ Element (RefElement c)
       , Seqs.IsSequence (RefElement c)
       )
    => c
    -> m (Maybe (CollElement c))
popFrontRef :: forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popFrontRef c
c = do
    RefElement c
l <- forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
c -> m (RefElement c)
readRef c
c
    case forall seq. IsSequence seq => seq -> Maybe (Element seq, seq)
Seqs.uncons RefElement c
l of
        Maybe (Element (RefElement c), RefElement c)
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
        Just (Element (RefElement c)
x, RefElement c
xs) -> do
            forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
c -> RefElement c -> m ()
writeRef c
c RefElement c
xs
            forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just Element (RefElement c)
x)
{-# INLINE popFrontRef #-}
instance Seqs.IsSequence a => MutablePopFront (IORef a) where
    popFront :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> m (Maybe (CollElement (IORef a)))
popFront = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popFrontRef
    {-# INLINE popFront #-}
instance Seqs.IsSequence a => MutablePopFront (STRef s a) where
    popFront :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a -> m (Maybe (CollElement (STRef s a)))
popFront = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popFrontRef
    {-# INLINE popFront #-}
instance Seqs.IsSequence a => MutablePopFront (MutVar s a) where
    popFront :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a -> m (Maybe (CollElement (MutVar s a)))
popFront = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popFrontRef
    {-# INLINE popFront #-}

-- | Place a value at the front of the collection.
--
-- Since 0.2.0
class MutableCollection c => MutablePushFront c where
    -- | Place a value at the front of the collection.
    --
    -- Since 0.2.0
    pushFront :: (PrimMonad m, PrimState m ~ MCState c)
              => c
              -> CollElement c
              -> m ()
pushFrontRef
    :: ( PrimMonad m
       , PrimState m ~ MCState c
       , MutableRef c
       , CollElement c ~ Element (RefElement c)
       , Seqs.IsSequence (RefElement c)
       )
    => c
    -> CollElement c
    -> m ()
pushFrontRef :: forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushFrontRef c
c CollElement c
e = forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
c -> (RefElement c -> RefElement c) -> m ()
modifyRef' c
c (forall seq. SemiSequence seq => Element seq -> seq -> seq
Seqs.cons CollElement c
e)
{-# INLINE pushFrontRef #-}
instance Seqs.IsSequence a => MutablePushFront (IORef a) where
    pushFront :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> CollElement (IORef a) -> m ()
pushFront = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushFrontRef
    {-# INLINE pushFront #-}
instance Seqs.IsSequence a => MutablePushFront (STRef s a) where
    pushFront :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a -> CollElement (STRef s a) -> m ()
pushFront = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushFrontRef
    {-# INLINE pushFront #-}
instance Seqs.IsSequence a => MutablePushFront (MutVar s a) where
    pushFront :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a -> CollElement (MutVar s a) -> m ()
pushFront = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushFrontRef
    {-# INLINE pushFront #-}

-- | Take a value from the back of the collection, if available.
--
-- Since 0.2.0
class MutableCollection c => MutablePopBack c where
    -- | Take a value from the back of the collection, if available.
    --
    -- Since 0.2.0
    popBack :: (PrimMonad m, PrimState m ~ MCState c)
            => c
            -> m (Maybe (CollElement c))
popBackRef
    :: ( PrimMonad m
       , PrimState m ~ MCState c
       , MutableRef c
       , CollElement c ~ Element (RefElement c)
       , Seqs.IsSequence (RefElement c)
       )
    => c
    -> m (Maybe (CollElement c))
popBackRef :: forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popBackRef c
c = do
    RefElement c
l <- forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
c -> m (RefElement c)
readRef c
c
    case forall seq. IsSequence seq => seq -> Maybe (seq, Element seq)
Seqs.unsnoc RefElement c
l of
        Maybe (RefElement c, Element (RefElement c))
Nothing -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a. Maybe a
Nothing
        Just (RefElement c
xs, Element (RefElement c)
x) -> do
            forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
c -> RefElement c -> m ()
writeRef c
c RefElement c
xs
            forall (m :: * -> *) a. Monad m => a -> m a
return (forall a. a -> Maybe a
Just Element (RefElement c)
x)
{-# INLINE popBackRef #-}
instance Seqs.IsSequence a => MutablePopBack (IORef a) where
    popBack :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> m (Maybe (CollElement (IORef a)))
popBack = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popBackRef
    {-# INLINE popBack #-}
instance Seqs.IsSequence a => MutablePopBack (STRef s a) where
    popBack :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a -> m (Maybe (CollElement (STRef s a)))
popBack = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popBackRef
    {-# INLINE popBack #-}
instance Seqs.IsSequence a => MutablePopBack (MutVar s a) where
    popBack :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a -> m (Maybe (CollElement (MutVar s a)))
popBack = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> m (Maybe (CollElement c))
popBackRef
    {-# INLINE popBack #-}

-- | Place a value at the back of the collection.
--
-- Since 0.2.0
class MutableCollection c => MutablePushBack c where
    -- | Place a value at the back of the collection.
    --
    -- Since 0.2.0
    pushBack :: (PrimMonad m, PrimState m ~ MCState c)
             => c
             -> CollElement c
             -> m ()
pushBackRef
    :: ( PrimMonad m
       , PrimState m ~ MCState c
       , MutableRef c
       , CollElement c ~ Element (RefElement c)
       , Seqs.IsSequence (RefElement c)
       )
    => c
    -> CollElement c
    -> m ()
pushBackRef :: forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushBackRef c
c CollElement c
e = forall c (m :: * -> *).
(MutableRef c, PrimMonad m, PrimState m ~ MCState c) =>
c -> (RefElement c -> RefElement c) -> m ()
modifyRef' c
c (forall seq. SemiSequence seq => seq -> Element seq -> seq
`Seqs.snoc` CollElement c
e)
{-# INLINE pushBackRef #-}
instance Seqs.IsSequence a => MutablePushBack (IORef a) where
    pushBack :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (IORef a)) =>
IORef a -> CollElement (IORef a) -> m ()
pushBack = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushBackRef
    {-# INLINE pushBack #-}
instance Seqs.IsSequence a => MutablePushBack (STRef s a) where
    pushBack :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (STRef s a)) =>
STRef s a -> CollElement (STRef s a) -> m ()
pushBack = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushBackRef
    {-# INLINE pushBack #-}
instance Seqs.IsSequence a => MutablePushBack (MutVar s a) where
    pushBack :: forall (m :: * -> *).
(PrimMonad m, PrimState m ~ MCState (MutVar s a)) =>
MutVar s a -> CollElement (MutVar s a) -> m ()
pushBack = forall (m :: * -> *) c.
(PrimMonad m, PrimState m ~ MCState c, MutableRef c,
 CollElement c ~ Element (RefElement c),
 IsSequence (RefElement c)) =>
c -> CollElement c -> m ()
pushBackRef
    {-# INLINE pushBack #-}

-- | Collections which allow pushing and popping at the front (aka FIFOs).
--
-- Since 0.2.0
type MutableQueue c = (MutablePopFront c, MutablePushBack c)

-- | Collections which allow pushing at the back and popping at the front (aka FILOs).
--
-- Since 0.2.0
type MutableStack c = (MutablePopFront c, MutablePushFront c)

-- | Collections which allow pushing and popping at the front and back.
--
-- Since 0.2.0
type MutableDeque c = (MutableQueue c, MutablePushFront c, MutablePopBack c)

-- |
-- Since 0.2.0
asIORef :: IORef a -> IORef a
asIORef :: forall a. IORef a -> IORef a
asIORef = forall a. a -> a
id

-- |
-- Since 0.2.0
asSTRef :: STRef s a -> STRef s a
asSTRef :: forall s a. STRef s a -> STRef s a
asSTRef = forall a. a -> a
id

-- |
-- Since 0.2.0
asMutVar :: MutVar s a -> MutVar s a
asMutVar :: forall s a. MutVar s a -> MutVar s a
asMutVar = forall a. a -> a
id