persistent-refs-0.4: src/Data/STRef/Persistent.hs
{-# LANGUAGE MultiParamTypeClasses #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
-----------------------------------------------------------------------------
-- |
-- Module : Data.STRef.Persistent
-- Copyright : (c) Adam C. Foltzer 2013
-- License : BSD3
--
-- Maintainer : acfoltzer@gmail.com
-- Stability : experimental
-- Portability : non-portable (requires rank-2 types for runST)
--
-- Mutable references in the persistent
-- 'Control.Monad.ST.Persistent.ST' monad.
--
-----------------------------------------------------------------------------
module Data.STRef.Persistent (
-- * 'STRef's
STRef
, asInt
-- * 'MonadRef' Operations
, MonadRef(..)
) where
import Control.Monad.State
import Control.Monad.Ref
import Control.Monad.ST.Persistent.Internal
import Data.IntMap as IntMap
import Data.Maybe
import Unsafe.Coerce
newtype STRef s a = STRef Int
deriving (Eq, Show)
-- | Get the underlying 'Int' from an 'STRef'. Useful for debugging.
asInt :: STRef s a -> Int
asInt (STRef i) = i
newSTRef :: Monad m => a -> STT s m (STRef s a)
newSTRef x = STT $ do
s <- get
let i = next s
heap' = insert i (unsafeCoerce x) (heap s)
next' = next s + 1
put $ s { heap = heap', next = next' }
return (STRef i)
readSTRef :: Monad m => STRef s a -> STT s m a
readSTRef (STRef i) = STT $
return . unsafeCoerce . fromJust . IntMap.lookup i =<< gets heap
writeSTRef :: Monad m => STRef s a -> a -> STT s m ()
writeSTRef (STRef i) x = STT $ do
s <- get
let heap' = insert i (unsafeCoerce x) (heap s)
put $ s { heap = heap' }
instance Monad m => MonadRef (STRef s) (STT s m) where
newRef = newSTRef
readRef = readSTRef
writeRef = writeSTRef