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: IOS (s: 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