Unsafe PrimMonad conversions
authorRoman Leshchinskiy <rl@cse.unsw.edu.au>
Fri, 4 Dec 2009 07:48:56 +0000 (07:48 +0000)
committerRoman Leshchinskiy <rl@cse.unsw.edu.au>
Fri, 4 Dec 2009 07:48:56 +0000 (07:48 +0000)
Control/Monad/Primitive.hs

index 44b247e..259217f 100644 (file)
 --
 
 module Control.Monad.Primitive (
-  PrimMonad(..), RealWorld, primitive_, primToIO, primToST
+  PrimMonad(..), RealWorld, primitive_,
+  primToPrim, primToIO, primToST,
+  unsafePrimToPrim, unsafePrimToIO, unsafePrimToST
 ) where
 
 import GHC.Prim   ( State#, RealWorld )
+import GHC.Base   ( unsafeCoerce# )
 import GHC.IOBase ( IO(..) )
 import GHC.ST     ( ST(..) )
 
@@ -47,11 +50,30 @@ instance PrimMonad (ST s) where
   primitive = ST
   internal (ST p) = p
 
+-- | Convert a 'PrimMonad' to another monad with the same state token.
+primToPrim :: (PrimMonad m1, PrimMonad m2, PrimState m1 ~ PrimState m2)
+        => m1 a -> m2 a
+primToPrim m = primitive (internal m)
+
 -- | Convert a 'PrimMonad' with a 'RealWorld' state token to 'IO'
 primToIO :: (PrimMonad m, PrimState m ~ RealWorld) => m a -> IO a
-primToIO p = IO (internal p)
+primToIO = primToPrim
 
 -- | Convert a 'PrimMonad' to 'ST'
 primToST :: PrimMonad m => m a -> ST (PrimState m) a
-primToST p = ST (internal p)
+primToST = primToPrim
+
+-- | Convert a 'PrimMonad' to another monad with a possibly different state
+-- token. This operation is highly unsafe!
+unsafePrimToPrim :: (PrimMonad m1, PrimMonad m2) => m1 a -> m2 a
+unsafePrimToPrim m = primitive (unsafeCoerce# (internal m))
+
+-- | Convert any 'PrimMonad' to 'ST' with an arbitrary state token. This
+-- operations is highly unsafe!
+unsafePrimToST :: PrimMonad m => m a -> ST s a
+unsafePrimToST = unsafePrimToPrim
+
+-- | Convert any 'PrimMonad' to 'IO'. This operation is highly unsafe!
+unsafePrimToIO :: PrimMonad m => m a -> IO a
+unsafePrimToIO = unsafePrimToPrim