monad-stlike-io-0.2.1: Control/Monad/STLike/IO.hs
module Control.Monad.STLike.IO
(-- * IOS monad
IOS, io, runIOS
-- * Regioned monad
,Regioned, runRegion, region, unfoldRegion
-- * Utilities
,RegionMonad, (:<), withRIOR, try, rbsFromPtr,rbsToBS,withRbsPtr,rbsMapLookup
) where
import qualified Control.Exception as E
import Control.Monad.STLike.Internal
import Control.Monad.Trans
import qualified Data.ByteString as B
import qualified Data.ByteString.Unsafe as B
import qualified Data.Map as M
import Foreign
-- | Monad for scoped IO computations
-- The underlying monad must be strict here.
type IOS s t = STLike IO s t
instance STLikeImpl IO
instance MonadIO (STLike IO s) where
liftIO x = io x
-- | Lift IO computations into IOS. liftIO also works.
io :: IO t -> IOS s t
io x = STLike x
try :: IOS s t -> IOS s (Either E.SomeException t)
try (STLike x) = STLike (E.try x)
-- | Run an IOS computation in the IO monad.
runIOS :: (forall s. IOS s t) -> IO t
runIOS x = let STLike v = x in v
{-
-- | Use a resource with IOS. Like /bracket/.
withRIOS :: (forall s. IOS (s :< o) (resource s)) -- ^ Open the resource
(forall s. (resource s -> IOS (s :< o) ())) -- ^ Close it.
(forall s. (resource s -> IOS (s :< o) result)) -- ^ Compute with it.
-> IOS o result
withRIOS (STLike open, close, work) = STLike (E.bracket open ioclose iowork)
where iowork x = let STLike w = work x in w
ioclose x = let STLike w = close x in w
-}
-- | Use a resource with IOS. Like /bracket/.
withRIOR :: IOS o resource -- ^ Open the resource
-> (resource -> IOS o ()) -- ^ Close it.
-> (forall s. Regioned (s:<o) resource -> IOS (s:<o) result) -- ^ Compute with it.
-> IOS o result
withRIOR (STLike open) close work = STLike (E.bracket open ioclose iowork)
where iowork x = let STLike w = work (R x) in w
ioclose x = let STLike w = close x in w
-- | Create a ByteString representing the pointer and length.
-- No copying done, O(1).
rbsFromPtr :: Ptr a -> Int -> IOS s (Regioned s B.ByteString)
rbsFromPtr ptr len = io $ fmap R $ B.unsafePackCStringLen (castPtr ptr,len)
-- | Create a copy of a regioned ByteString as a normal ByteString. O(n).
rbsToBS :: RegionMonad m s reg => Regioned s B.ByteString -> STLike m reg B.ByteString
rbsToBS (R b) = return $! B.copy b
-- | Use a regioned ByteString as a pointer. O(1).
-- The pointer points to the region contents,
-- so be cafeful with it.
withRbsPtr :: Regioned s B.ByteString -> (Ptr any -> Int -> IOS s t) -> IOS s t
--withRbsPtr (R b) act = io $ B.unsafeUseAsCStringLen b (\(p,l) -> unsafeSTToIO (act (castPtr p) l))
withRbsPtr (R b) act = io $ B.unsafeUseAsCStringLen b (\(p,l) -> let STLike v = (act (castPtr p) l) in v)
-- | Lookup inside a Map with a regioned ByteString.
rbsMapLookup :: (RegionMonad m s reg, Ord key) => Regioned s key -> M.Map key value -> STLike m reg (Maybe value)
rbsMapLookup (R k) m = case M.lookup k m of
Just x -> return (Just x)
Nothing -> return Nothing
-- | Regions a value. Synonym for /return/.
region :: t -> Regioned s t
region = R