module Lava.MyST ( ST , STRef , newSTRef , readSTRef , writeSTRef , runST , fixST , unsafePerformST , unsafeInterleaveST , unsafeIOtoST ) where import Control.Applicative (Applicative (..)) import Control.Monad (ap) import System.IO import System.IO.Unsafe import Data.IORef newtype ST s a = ST (IO a) unST :: ST s a -> IO a unST (ST io) = io instance Functor (ST s) where fmap f (ST io) = ST (fmap f io) instance Applicative (ST s) where pure = return (<*>) = ap instance Monad (ST s) where return a = ST (return a) ST io >>= k = ST (do a <- io ; unST (k a)) newtype STRef s a = STRef (IORef a) instance Eq (STRef s a) where STRef r1 == STRef r2 = r1 == r2 newSTRef :: a -> ST s (STRef s a) newSTRef a = ST (STRef `fmap` newIORef a) readSTRef :: STRef s a -> ST s a readSTRef (STRef r) = ST (readIORef r) writeSTRef :: STRef s a -> a -> ST s () writeSTRef (STRef r) a = ST (writeIORef r a) runST :: (forall s . ST s a) -> a runST st = unsafePerformST st fixST :: (a -> ST s a) -> ST s a fixST f = ST (fixIO (unST . f)) unsafePerformST :: ST s a -> a unsafePerformST (ST io) = unsafePerformIO io unsafeInterleaveST :: ST s a -> ST s a unsafeInterleaveST (ST io) = ST (unsafeInterleaveIO io) unsafeIOtoST :: IO a -> ST s a unsafeIOtoST = ST