{-# LANGUAGE MagicHash #-} {-# LANGUAGE UnboxedTuples #-} {-# LANGUAGE NoImplicitPrelude #-} -- | -- Module : Data.PrimRef -- Copyright : (c) 2013 Aleksey Khudyakov -- License : BSD3 -- -- Maintainer : alexey.skladnoy@gmail.com -- Stability : experimental -- Portability : portable -- -- Mutable references in monads which are instances of 'MonadPrim'. module Data.PrimRef ( -- * PrimRefs PrimRef , newPrimRef , readPrimRef , writePrimRef , modifyPrimRef , modifyPrimRef' ) where import Control.Monad.Primitive (PrimMonad(..)) import GHC.Base (MutVar#,newMutVar#,readMutVar#,writeMutVar#) import Prelude (($),($!)) -- | Mutable variable which full analog of 'Data.IORef.IORef' or -- 'Data.STRef.STRef' but could use either of the monads. -- Unfortunately there's no way to convert @PrimRef@ to @STRef@ or -- @IORef@. data PrimRef m a = PrimRef (MutVar# (PrimState m) a) -- | Create new mutable variable with initial value @a@. newPrimRef :: PrimMonad m => a -> m (PrimRef m a) newPrimRef a = primitive $ \s1# -> case newMutVar# a s1# of (# s2#, var# #) -> (# s2#, PrimRef var# #) -- | Read value of @PrimRef@. readPrimRef :: PrimMonad m => PrimRef m a -> m a readPrimRef (PrimRef var#) = primitive $ \s1# -> readMutVar# var# s1# -- | Write value to @PrimRef@. writePrimRef :: PrimMonad m => PrimRef m a -> a -> m () writePrimRef (PrimRef var#) a = primitive $ \s1# -> case writeMutVar# var# a s1# of s2# -> (# s2#, () #) -- | Modify content of @PrimRef@ using function. modifyPrimRef :: PrimMonad m => PrimRef m a -> (a -> a) -> m () modifyPrimRef var f = do x <- readPrimRef var writePrimRef var $ f x -- | Modify content of @PrimRef@ using function and evaluate result of -- function application to WHNF before storing it in the variable. modifyPrimRef' :: PrimMonad m => PrimRef m a -> (a -> a) -> m () modifyPrimRef' var f = do x <- readPrimRef var writePrimRef var $! f x