(original) (raw)

{-# LANGUAGE Trustworthy #-}


-- Maintainer : libraries@haskell.org -- Stability : experimental -- Portability : non-portable (uses Control.Monad.ST)

-- Mutable references in the (strict) ST monad.


module Data.STRef ( -- * STRefs STRef, -- abstract newSTRef, readSTRef, writeSTRef, modifySTRef, modifySTRef' ) where

import GHC.ST import GHC.STRef

-- | Mutate the contents of an 'STRef'.

-- >>> :{ -- runST (do -- ref <- newSTRef "" -- modifySTRef ref (const "world") -- modifySTRef ref (++ "!") -- modifySTRef ref ("Hello, " ++) -- readSTRef ref ) -- :} -- "Hello, world!"

-- Be warned that 'modifySTRef' does not apply the function strictly. This -- means if the program calls 'modifySTRef' many times, but seldomly uses the -- value, thunks will pile up in memory resulting in a space leak. This is a -- common mistake made when using an STRef as a counter. For example, the -- following will leak memory and may produce a stack overflow:

-- >>> import Control.Monad (replicateM_) -- >>> :{ -- print (runST (do -- ref <- newSTRef 0 -- replicateM_ 1000 $ modifySTRef ref (+1) -- readSTRef ref )) -- :} -- 1000

-- To avoid this problem, use 'modifySTRef'' instead. modifySTRef :: STRef s a -> (a -> a) -> ST s () modifySTRef ref f = writeSTRef ref . f =<< readSTRef ref

-- | Strict version of 'modifySTRef'

-- @since 4.6.0.0 modifySTRef' :: STRef s a -> (a -> a) -> ST s () modifySTRef' ref f = do x <- readSTRef ref let x' = f x x' seq writeSTRef ref x'