content: {-# LANGUAGE TypeFamilies #-}
  -- | Use 1-length mutable unboxed vectors for mutable references.
  --
  -- Motivated by: <http://stackoverflow.com/questions/27261813/why-is-my-little-stref-int-require-allocating-gigabytes> and ArrayRef.
  module Data.Mutable.URef
      ( -- * Types
        URef
      , IOURef
        -- * Functions
      , asURef
      , MutableRef (..)
      ) where
  
  import           Control.Monad               (liftM)
  import           Data.Mutable.Class
  import qualified Data.Vector.Generic.Mutable as V
  import qualified Data.Vector.Unboxed.Mutable as VU
  
  -- | An unboxed vector reference, supporting any monad.
  --
  -- Since 0.2.0
  newtype URef s a = URef (VU.MVector s a)
  
  -- |
  -- Since 0.2.0
  asURef :: URef s a -> URef s a
  asURef x = x
  {-# INLINE asURef #-}
  
  -- | An unboxed IO vector reference.
  type IOURef = URef (PrimState IO)
  
  instance MutableContainer (URef s a) where
      type MCState (URef s a) = s
  instance VU.Unbox a => MutableRef (URef s a) where
      type RefElement (URef s a) = a
  
      newRef = liftM URef . V.replicate 1
      {-# INLINE newRef#-}
  
      readRef (URef v) = V.unsafeRead v 0
      {-# INLINE readRef #-}
  
      writeRef (URef v) = V.unsafeWrite v 0
      {-# INLINE writeRef #-}
  
      modifyRef (URef v) f = V.unsafeRead v 0 >>= V.unsafeWrite v 0 . f
      {-# INLINE modifyRef #-}
  
      modifyRef' = modifyRef
      {-# INLINE modifyRef' #-}
  