packages feed

statethread-0.1: src/Control/Monad/ST/Strict.hs

{-# LANGUAGE Rank2Types #-}
module Control.Monad.ST.Strict (
   ST, runST, fixST,

   RealWorld, stToIO,

   unsafeInterleaveST,
   unsafeIOToST,
   unsafeSTToIO,
   ) where

import Control.Monad.Fix (MonadFix, mfix, )
import Control.Applicative (Applicative(pure, (<*>)), )
import System.IO.Unsafe (unsafePerformIO, unsafeInterleaveIO, )
import System.IO (fixIO, )


-- * The 'ST' Monad

newtype ST s a = ST {unST :: IO a}

instance Functor (ST s) where
   fmap f (ST st) = ST (fmap f st)

instance Applicative (ST s) where
   pure f = ST (pure f)
   ST f <*> ST x = ST (f <*> x)

instance Monad (ST s) where
   return f = ST (return f)
   fail str = ST (fail str)
   ST x >> ST y = ST (x >> y)
   ST x >>= k = ST (unST . k =<< x)


runST :: (forall s. ST s a) -> a
runST st = unsafePerformIO (unST st)

fixST :: (a -> ST s a) -> ST s a
fixST f = ST (fixIO (unST . f))

instance MonadFix (ST s) where
   mfix = fixST


-- * Converting 'ST' to 'IO'

data RealWorld = RealWorld

stToIO :: ST RealWorld a -> IO a
stToIO = unST


-- * Unsafe operations

unsafeInterleaveST :: ST s a -> ST s a
unsafeInterleaveST (ST st) =
   ST (unsafeInterleaveIO st)

unsafeIOToST :: IO a -> ST s a
unsafeIOToST = ST

unsafeSTToIO :: ST s a -> IO a
unsafeSTToIO = unST