{-# LANGUAGE CPP, MagicHash, UnboxedTuples, TypeFamilies #-}
module Control.Monad.Primitive (
PrimMonad(..), RealWorld, primitive_,
primToPrim, primToIO, primToST,
unsafePrimToPrim, unsafePrimToIO, unsafePrimToST,
unsafeInlinePrim, unsafeInlineIO, unsafeInlineST,
touch
) where
import GHC.Prim ( State#, RealWorld, touch# )
import GHC.Base ( unsafeCoerce#, realWorld# )
#if MIN_VERSION_base(4,2,0)
import GHC.IO ( IO(..) )
#else
import GHC.IOBase ( IO(..) )
#endif
import GHC.ST ( ST(..) )
class Monad m => PrimMonad m where
type PrimState m
primitive :: (State# (PrimState m) -> (# State# (PrimState m), a #)) -> m a
internal :: m a -> State# (PrimState m) -> (# State# (PrimState m), a #)
primitive_ :: PrimMonad m
=> (State# (PrimState m) -> State# (PrimState m)) -> m ()
{-# INLINE primitive_ #-}
primitive_ f = primitive (\s# -> (# f s#, () #))
instance PrimMonad IO where
type PrimState IO = RealWorld
primitive = IO
internal (IO p) = p
{-# INLINE primitive #-}
{-# INLINE internal #-}
instance PrimMonad (ST s) where
type PrimState (ST s) = s
primitive = ST
internal (ST p) = p
{-# INLINE primitive #-}
{-# INLINE internal #-}
primToPrim :: (PrimMonad m1, PrimMonad m2, PrimState m1 ~ PrimState m2)
=> m1 a -> m2 a
{-# INLINE primToPrim #-}
primToPrim m = primitive (internal m)
primToIO :: (PrimMonad m, PrimState m ~ RealWorld) => m a -> IO a
{-# INLINE primToIO #-}
primToIO = primToPrim
primToST :: PrimMonad m => m a -> ST (PrimState m) a
{-# INLINE primToST #-}
primToST = primToPrim
unsafePrimToPrim :: (PrimMonad m1, PrimMonad m2) => m1 a -> m2 a
{-# INLINE unsafePrimToPrim #-}
unsafePrimToPrim m = primitive (unsafeCoerce# (internal m))
unsafePrimToST :: PrimMonad m => m a -> ST s a
{-# INLINE unsafePrimToST #-}
unsafePrimToST = unsafePrimToPrim
unsafePrimToIO :: PrimMonad m => m a -> IO a
{-# INLINE unsafePrimToIO #-}
unsafePrimToIO = unsafePrimToPrim
unsafeInlinePrim :: PrimMonad m => m a -> a
{-# INLINE unsafeInlinePrim #-}
unsafeInlinePrim m = unsafeInlineIO (unsafePrimToIO m)
unsafeInlineIO :: IO a -> a
{-# INLINE unsafeInlineIO #-}
unsafeInlineIO m = case internal m realWorld# of (# _, r #) -> r
unsafeInlineST :: ST s a -> a
{-# INLINE unsafeInlineST #-}
unsafeInlineST = unsafeInlinePrim
touch :: PrimMonad m => a -> m ()
{-# INLINE touch #-}
touch x = unsafePrimToPrim
$ (primitive (\s -> case touch# x s of { s' -> (# s', () #) }) :: IO ())