resourcet 0.4.7.2 → 0.4.8
raw patch · 3 files changed
+426/−361 lines, 3 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- Control.Monad.Trans.Resource: instance (Error e, MonadResource m) => MonadResource (ErrorT e m)
- Control.Monad.Trans.Resource: instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m)
- Control.Monad.Trans.Resource: instance (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource (ResourceT m)
- Control.Monad.Trans.Resource: instance (MonadTrans t, MonadUnsafeIO m, Monad (t m)) => MonadUnsafeIO (t m)
- Control.Monad.Trans.Resource: instance (Monoid w, MonadResource m) => MonadResource (RWST r w s m)
- Control.Monad.Trans.Resource: instance (Monoid w, MonadResource m) => MonadResource (WriterT w m)
- Control.Monad.Trans.Resource: instance (Monoid w, MonadThrow m) => MonadThrow (RWST r w s m)
- Control.Monad.Trans.Resource: instance (Monoid w, MonadThrow m) => MonadThrow (WriterT w m)
- Control.Monad.Trans.Resource: instance Applicative m => Applicative (ResourceT m)
- Control.Monad.Trans.Resource: instance Exception InvalidAccess
- Control.Monad.Trans.Resource: instance Functor m => Functor (ResourceT m)
- Control.Monad.Trans.Resource: instance MFunctor ResourceT
- Control.Monad.Trans.Resource: instance MMonad ResourceT
- Control.Monad.Trans.Resource: instance Monad m => Applicative (ExceptionT m)
- Control.Monad.Trans.Resource: instance Monad m => Functor (ExceptionT m)
- Control.Monad.Trans.Resource: instance Monad m => Monad (ExceptionT m)
- Control.Monad.Trans.Resource: instance Monad m => Monad (ResourceT m)
- Control.Monad.Trans.Resource: instance Monad m => MonadThrow (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadBase b m => MonadBase b (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadBase b m => MonadBase b (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadBaseControl b m => MonadBaseControl b (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadBaseControl b m => MonadBaseControl b (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadCont m => MonadCont (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadCont m => MonadCont (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadError e m => MonadError e (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadError e m => MonadError e (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadIO m => MonadIO (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadIO m => MonadIO (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadRWS r w s m => MonadRWS r w s (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadRWS r w s m => MonadRWS r w s (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadReader r m => MonadReader r (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadReader r m => MonadReader r (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (ContT r m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (IdentityT m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (ListT m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (MaybeT m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (ReaderT r m)
- Control.Monad.Trans.Resource: instance MonadResource m => MonadResource (StateT s m)
- Control.Monad.Trans.Resource: instance MonadState s m => MonadState s (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadState s m => MonadState s (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadThrow (Either SomeException)
- Control.Monad.Trans.Resource: instance MonadThrow IO
- Control.Monad.Trans.Resource: instance MonadThrow Maybe
- Control.Monad.Trans.Resource: instance MonadThrow []
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (ContT r m)
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (IdentityT m)
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (ListT m)
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (MaybeT m)
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (ReaderT r m)
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (ResourceT m)
- Control.Monad.Trans.Resource: instance MonadThrow m => MonadThrow (StateT s m)
- Control.Monad.Trans.Resource: instance MonadTrans ExceptionT
- Control.Monad.Trans.Resource: instance MonadTrans ResourceT
- Control.Monad.Trans.Resource: instance MonadTransControl ExceptionT
- Control.Monad.Trans.Resource: instance MonadTransControl ResourceT
- Control.Monad.Trans.Resource: instance MonadUnsafeIO (ST s)
- Control.Monad.Trans.Resource: instance MonadUnsafeIO IO
- Control.Monad.Trans.Resource: instance MonadWriter w m => MonadWriter w (ExceptionT m)
- Control.Monad.Trans.Resource: instance MonadWriter w m => MonadWriter w (ResourceT m)
- Control.Monad.Trans.Resource: instance Show InvalidAccess
- Control.Monad.Trans.Resource: instance Typeable InvalidAccess
- Control.Monad.Trans.Resource: instance Typeable ReleaseKey
- Control.Monad.Trans.Resource: instance Typeable1 m => Typeable1 (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: ExceptionT :: m (Either SomeException a) -> ExceptionT m a
+ Control.Monad.Trans.Resource.Internal: InvalidAccess :: String -> InvalidAccess
+ Control.Monad.Trans.Resource.Internal: ReleaseKey :: !(IORef ReleaseMap) -> !Int -> ReleaseKey
+ Control.Monad.Trans.Resource.Internal: ReleaseMap :: !NextKey -> !RefCount -> !(IntMap (IO ())) -> ReleaseMap
+ Control.Monad.Trans.Resource.Internal: ReleaseMapClosed :: ReleaseMap
+ Control.Monad.Trans.Resource.Internal: ResourceT :: (IORef ReleaseMap -> m a) -> ResourceT m a
+ Control.Monad.Trans.Resource.Internal: class (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource m
+ Control.Monad.Trans.Resource.Internal: class Monad m => MonadThrow m
+ Control.Monad.Trans.Resource.Internal: class Monad m => MonadUnsafeIO m
+ Control.Monad.Trans.Resource.Internal: data InvalidAccess
+ Control.Monad.Trans.Resource.Internal: data ReleaseKey
+ Control.Monad.Trans.Resource.Internal: data ReleaseMap
+ Control.Monad.Trans.Resource.Internal: functionName :: InvalidAccess -> String
+ Control.Monad.Trans.Resource.Internal: instance (Error e, MonadResource m) => MonadResource (ErrorT e m)
+ Control.Monad.Trans.Resource.Internal: instance (Error e, MonadThrow m) => MonadThrow (ErrorT e m)
+ Control.Monad.Trans.Resource.Internal: instance (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance (MonadTrans t, MonadUnsafeIO m, Monad (t m)) => MonadUnsafeIO (t m)
+ Control.Monad.Trans.Resource.Internal: instance (Monoid w, MonadResource m) => MonadResource (RWST r w s m)
+ Control.Monad.Trans.Resource.Internal: instance (Monoid w, MonadResource m) => MonadResource (WriterT w m)
+ Control.Monad.Trans.Resource.Internal: instance (Monoid w, MonadThrow m) => MonadThrow (RWST r w s m)
+ Control.Monad.Trans.Resource.Internal: instance (Monoid w, MonadThrow m) => MonadThrow (WriterT w m)
+ Control.Monad.Trans.Resource.Internal: instance Applicative m => Applicative (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance Exception InvalidAccess
+ Control.Monad.Trans.Resource.Internal: instance Functor m => Functor (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MFunctor ResourceT
+ Control.Monad.Trans.Resource.Internal: instance MMonad ResourceT
+ Control.Monad.Trans.Resource.Internal: instance Monad m => Applicative (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance Monad m => Functor (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance Monad m => Monad (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance Monad m => Monad (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance Monad m => MonadThrow (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadBase b m => MonadBase b (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadBase b m => MonadBase b (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadBaseControl b m => MonadBaseControl b (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadBaseControl b m => MonadBaseControl b (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadCont m => MonadCont (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadCont m => MonadCont (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadError e m => MonadError e (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadError e m => MonadError e (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadIO m => MonadIO (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadIO m => MonadIO (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadRWS r w s m => MonadRWS r w s (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadRWS r w s m => MonadRWS r w s (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadReader r m => MonadReader r (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadReader r m => MonadReader r (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (ContT r m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (IdentityT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (ListT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (MaybeT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (ReaderT r m)
+ Control.Monad.Trans.Resource.Internal: instance MonadResource m => MonadResource (StateT s m)
+ Control.Monad.Trans.Resource.Internal: instance MonadState s m => MonadState s (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadState s m => MonadState s (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow (Either SomeException)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow IO
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow Maybe
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow []
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (ContT r m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (IdentityT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (ListT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (MaybeT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (ReaderT r m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadThrow m => MonadThrow (StateT s m)
+ Control.Monad.Trans.Resource.Internal: instance MonadTrans ExceptionT
+ Control.Monad.Trans.Resource.Internal: instance MonadTrans ResourceT
+ Control.Monad.Trans.Resource.Internal: instance MonadTransControl ExceptionT
+ Control.Monad.Trans.Resource.Internal: instance MonadTransControl ResourceT
+ Control.Monad.Trans.Resource.Internal: instance MonadUnsafeIO (ST s)
+ Control.Monad.Trans.Resource.Internal: instance MonadUnsafeIO IO
+ Control.Monad.Trans.Resource.Internal: instance MonadWriter w m => MonadWriter w (ExceptionT m)
+ Control.Monad.Trans.Resource.Internal: instance MonadWriter w m => MonadWriter w (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: instance Show InvalidAccess
+ Control.Monad.Trans.Resource.Internal: instance Typeable InvalidAccess
+ Control.Monad.Trans.Resource.Internal: instance Typeable ReleaseKey
+ Control.Monad.Trans.Resource.Internal: instance Typeable1 m => Typeable1 (ResourceT m)
+ Control.Monad.Trans.Resource.Internal: liftResourceT :: MonadResource m => ResourceT IO a -> m a
+ Control.Monad.Trans.Resource.Internal: monadThrow :: (MonadThrow m, Exception e) => e -> m a
+ Control.Monad.Trans.Resource.Internal: newtype ExceptionT m a
+ Control.Monad.Trans.Resource.Internal: newtype ResourceT m a
+ Control.Monad.Trans.Resource.Internal: runExceptionT :: ExceptionT m a -> m (Either SomeException a)
+ Control.Monad.Trans.Resource.Internal: stateAlloc :: IORef ReleaseMap -> IO ()
+ Control.Monad.Trans.Resource.Internal: stateCleanup :: IORef ReleaseMap -> IO ()
+ Control.Monad.Trans.Resource.Internal: transResourceT :: (m a -> n b) -> ResourceT m a -> ResourceT n b
+ Control.Monad.Trans.Resource.Internal: type ResIO a = ResourceT IO a
+ Control.Monad.Trans.Resource.Internal: unResourceT :: ResourceT m a -> IORef ReleaseMap -> m a
+ Control.Monad.Trans.Resource.Internal: unsafeLiftIO :: MonadUnsafeIO m => IO a -> m a
Files
- Control/Monad/Trans/Resource.hs +4/−360
- Control/Monad/Trans/Resource/Internal.hs +420/−0
- resourcet.cabal +2/−1
Control/Monad/Trans/Resource.hs view
@@ -38,7 +38,7 @@ , allocate , register , release- , unprotect + , unprotect , resourceMask -- * Type class/associated types , MonadResource (..)@@ -58,19 +58,13 @@ , withInternalState ) where -import Data.Typeable-import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap-import Control.Exception (SomeException, throw, Exception)+import Control.Exception (SomeException, throw) import Control.Monad.Trans.Control- ( MonadTransControl (..), MonadBaseControl (..)- , ComposeSt, defaultLiftBaseWith, defaultRestoreM- , liftBaseDiscard, control- )+ ( MonadBaseControl (..), liftBaseDiscard, control ) import qualified Data.IORef as I import Control.Monad.Base (MonadBase, liftBase) import Control.Applicative (Applicative (..))-import Control.Monad.Trans.Class (MonadTrans (..)) import Control.Monad.IO.Class (MonadIO (..)) import Control.Monad (liftM) import qualified Control.Exception as E@@ -82,134 +76,26 @@ import Control.Monad.Trans.Maybe ( MaybeT ) import Control.Monad.Trans.Error ( ErrorT, Error) import Control.Monad.Trans.Reader ( ReaderT )-import Control.Monad.Trans.Cont ( ContT ) import Control.Monad.Trans.State ( StateT ) import Control.Monad.Trans.Writer ( WriterT )+import Control.Monad.Trans.Resource.Internal import Control.Monad.Trans.RWS ( RWST ) -import Control.Monad.Cont.Class ( MonadCont (..) )-import Control.Monad.Error.Class ( MonadError (..) )-import Control.Monad.RWS.Class ( MonadRWS )-import Control.Monad.Reader.Class ( MonadReader (..) )-import Control.Monad.State.Class ( MonadState (..) )-import Control.Monad.Writer.Class ( MonadWriter (..) )--import Data.Word (Word)- import qualified Control.Monad.Trans.RWS.Strict as Strict ( RWST ) import qualified Control.Monad.Trans.State.Strict as Strict ( StateT ) import qualified Control.Monad.Trans.Writer.Strict as Strict ( WriterT ) import Control.Concurrent (ThreadId, forkIO) import Control.Monad.ST (ST)-#if __GLASGOW_HASKELL__ >= 704-import Control.Monad.ST.Unsafe (unsafeIOToST)-#else-import Control.Monad.ST (unsafeIOToST)-#endif -#if __GLASGOW_HASKELL__ >= 704-import qualified Control.Monad.ST.Lazy.Unsafe as LazyUnsafe-#else-import qualified Control.Monad.ST.Lazy as LazyUnsafe-#endif- import qualified Control.Monad.ST.Lazy as Lazy import Data.Functor.Identity (Identity, runIdentity) import Control.Monad.Morph --- | A lookup key for a specific release action. This value is returned by--- 'register' and 'allocate', and is passed to 'release'.------ Since 0.3.0-data ReleaseKey = ReleaseKey !(I.IORef ReleaseMap) !Int- deriving Typeable -type RefCount = Word-type NextKey = Int -data ReleaseMap =- ReleaseMap !NextKey !RefCount !(IntMap (IO ()))- | ReleaseMapClosed --- | The Resource transformer. This transformer keeps track of all registered--- actions, and calls them upon exit (via 'runResourceT'). Actions may be--- registered via 'register', or resources may be allocated atomically via--- 'allocate'. @allocate@ corresponds closely to @bracket@.------ Releasing may be performed before exit via the 'release' function. This is a--- highly recommended optimization, as it will ensure that scarce resources are--- freed early. Note that calling @release@ will deregister the action, so that--- a release action will only ever be called once.------ Since 0.3.0-newtype ResourceT m a = ResourceT { unResourceT :: I.IORef ReleaseMap -> m a }-#if __GLASGOW_HASKELL__ >= 707- deriving Typeable-#else-instance Typeable1 m => Typeable1 (ResourceT m) where- typeOf1 = goType undefined- where- goType :: Typeable1 m => m a -> ResourceT m a -> TypeRep- goType m _ =- mkTyConApp-#if __GLASGOW_HASKELL__ >= 704- (mkTyCon3 "resourcet" "Control.Monad.Trans.Resource" "ResourceT")-#else- (mkTyCon "Control.Monad.Trans.Resource.ResourceT")-#endif- [ typeOf1 m- ]-#endif---- | Convenient alias for @ResourceT IO@.-type ResIO a = ResourceT IO a---instance MonadCont m => MonadCont (ResourceT m) where- callCC f = ResourceT $ \i -> callCC $ \c -> unResourceT (f (ResourceT . const . c)) i--instance MonadError e m => MonadError e (ResourceT m) where- throwError = lift . throwError- catchError r h = ResourceT $ \i -> unResourceT r i `catchError` \e -> unResourceT (h e) i--instance MonadRWS r w s m => MonadRWS r w s (ResourceT m)--instance MonadReader r m => MonadReader r (ResourceT m) where- ask = lift ask- local = mapResourceT . local--mapResourceT :: (m a -> n b) -> ResourceT m a -> ResourceT n b-mapResourceT f = ResourceT . (f .) . unResourceT--instance MonadState s m => MonadState s (ResourceT m) where- get = lift get- put = lift . put--instance MonadWriter w m => MonadWriter w (ResourceT m) where- tell = lift . tell- listen = mapResourceT listen- pass = mapResourceT pass----- | A @Monad@ which allows for safe resource allocation. In theory, any monad--- transformer stack included a @ResourceT@ can be an instance of--- @MonadResource@.------ Note: @runResourceT@ has a requirement for a @MonadBaseControl IO m@ monad,--- which allows control operations to be lifted. A @MonadResource@ does not--- have this requirement. This means that transformers such as @ContT@ can be--- an instance of @MonadResource@. However, the @ContT@ wrapper will need to be--- unwrapped before calling @runResourceT@.------ Since 0.3.0-class (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource m where- -- | Lift a @ResourceT IO@ action into the current @Monad@.- --- -- Since 0.4.0- liftResourceT :: ResourceT IO a -> m a- -- | Register some action that will be called precisely once, either when -- 'runResourceT' is called, or when the 'ReleaseKey' is passed to 'release'. --@@ -256,9 +142,6 @@ resourceMask :: MonadResource m => ((forall a. ResourceT IO a -> ResourceT IO a) -> ResourceT IO b) -> m b resourceMask = liftResourceT . resourceMaskRIO -instance (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource (ResourceT m) where- liftResourceT = transResourceT liftIO- allocateRIO :: IO a -> (a -> IO ()) -> ResourceT IO (ReleaseKey, a) allocateRIO acquire rel = ResourceT $ \istate -> liftIO $ E.mask $ \restore -> do a <- restore acquire@@ -276,23 +159,6 @@ go :: (forall a. IO a -> IO a) -> (forall a. ResourceT IO a -> ResourceT IO a) go r (ResourceT g) = ResourceT (\i -> r (g i)) -#define GO(T) instance (MonadResource m) => MonadResource (T m) where liftResourceT = lift . liftResourceT-#define GOX(X, T) instance (X, MonadResource m) => MonadResource (T m) where liftResourceT = lift . liftResourceT-GO(IdentityT)-GO(ListT)-GO(MaybeT)-GOX(Error e, ErrorT e)-GO(ReaderT r)-GO(ContT r)-GO(StateT s)-GOX(Monoid w, WriterT w)-GOX(Monoid w, RWST r w s)-GOX(Monoid w, Strict.RWST r w s)-GO(Strict.StateT s)-GOX(Monoid w, Strict.WriterT w)-#undef GO-#undef GOX- register' :: I.IORef ReleaseMap -> IO () -> IO ReleaseKey@@ -304,22 +170,8 @@ ) ReleaseMapClosed -> throw $ InvalidAccess "register'" --- | Indicates either an error in the library, or misuse of it (e.g., a--- @ResourceT@'s state is accessed after being released).------ Since 0.3.0-data InvalidAccess = InvalidAccess { functionName :: String }- deriving Typeable -instance Show InvalidAccess where- show (InvalidAccess f) = concat- [ "Control.Monad.Trans.Resource."- , f- , ": The mutable state is being accessed after cleanup. Please contact the maintainers."- ] -instance Exception InvalidAccess- release' :: I.IORef ReleaseMap -> Int -> (Maybe (IO ()) -> IO a)@@ -342,31 +194,7 @@ -- 0.4.4, it's no longer a library misuse or a library bug. lookupAction ReleaseMapClosed = (ReleaseMapClosed, Nothing) -stateAlloc :: I.IORef ReleaseMap -> IO ()-stateAlloc istate = do- I.atomicModifyIORef istate $ \rm ->- case rm of- ReleaseMap nk rf m ->- (ReleaseMap nk (rf + 1) m, ())- ReleaseMapClosed -> throw $ InvalidAccess "stateAlloc" -stateCleanup :: I.IORef ReleaseMap -> IO ()-stateCleanup istate = E.mask_ $ do- mm <- I.atomicModifyIORef istate $ \rm ->- case rm of- ReleaseMap nk rf m ->- let rf' = rf - 1- in if rf' == minBound- then (ReleaseMapClosed, Just m)- else (ReleaseMap nk rf' m, Nothing)- ReleaseMapClosed -> throw $ InvalidAccess "stateCleanup"- case mm of- Just m ->- mapM_ (\x -> try x >> return ()) $ IntMap.elems m- Nothing -> return ()- where- try :: IO a -> IO (Either SomeException a)- try = E.try -- | Unwrap a 'ResourceT' transformer, and call all registered release actions. --@@ -388,23 +216,7 @@ bracket_ alloc cleanup inside = control $ \run -> E.bracket_ alloc cleanup (run inside) --- | Transform the monad a @ResourceT@ lives in. This is most often used to--- strip or add new transformers to a stack, e.g. to run a @ReaderT@.------ Note that this function is a slight generalization of 'hoist'.------ Since 0.3.0-transResourceT :: (m a -> n b)- -> ResourceT m a- -> ResourceT n b-transResourceT f (ResourceT mx) = ResourceT (\r -> f (mx r)) --- | Since 0.4.7-instance MFunctor ResourceT where- hoist f (ResourceT mx) = ResourceT (\r -> f (mx r))--- | Since 0.4.7-instance MMonad ResourceT where- embed f m = ResourceT (\i -> unResourceT (f (unResourceT m i)) i) -- | This function mirrors @join@ at the transformer level: it will collapse -- two levels of @ResourceT@ into a single @ResourceT@.@@ -414,57 +226,8 @@ -> ResourceT m a joinResourceT (ResourceT f) = ResourceT $ \r -> unResourceT (f r) r --------- All of our monad et al instances-instance Functor m => Functor (ResourceT m) where- fmap f (ResourceT m) = ResourceT $ \r -> fmap f (m r) -instance Applicative m => Applicative (ResourceT m) where- pure = ResourceT . const . pure- ResourceT mf <*> ResourceT ma = ResourceT $ \r ->- mf r <*> ma r -instance Monad m => Monad (ResourceT m) where- return = ResourceT . const . return- ResourceT ma >>= f = ResourceT $ \r -> do- a <- ma r- let ResourceT f' = f a- f' r--instance MonadTrans ResourceT where- lift = ResourceT . const--instance MonadIO m => MonadIO (ResourceT m) where- liftIO = lift . liftIO--instance MonadBase b m => MonadBase b (ResourceT m) where- liftBase = lift . liftBase--instance MonadTransControl ResourceT where- newtype StT ResourceT a = StReader {unStReader :: a}- liftWith f = ResourceT $ \r -> f $ \(ResourceT t) -> liftM StReader $ t r- restoreT = ResourceT . const . liftM unStReader- {-# INLINE liftWith #-}- {-# INLINE restoreT #-}--instance MonadBaseControl b m => MonadBaseControl b (ResourceT m) where- newtype StM (ResourceT m) a = StMT (StM m a)- liftBaseWith f = ResourceT $ \reader ->- liftBaseWith $ \runInBase ->- f $ liftM StMT . runInBase . (\(ResourceT r) -> r reader)- restoreM (StMT base) = ResourceT $ const $ restoreM base-instance Monad m => MonadThrow (ExceptionT m) where- monadThrow = ExceptionT . return . Left . E.toException-instance MonadResource m => MonadResource (ExceptionT m) where- liftResourceT = lift . liftResourceT-instance MonadIO m => MonadIO (ExceptionT m) where- liftIO = lift . liftIO---- | The express purpose of this transformer is to allow non-@IO@-based monad--- stacks to catch exceptions via the 'MonadThrow' typeclass.------ Since 0.3.0-newtype ExceptionT m a = ExceptionT { runExceptionT :: m (Either SomeException a) }- -- | Same as 'runExceptionT', but immediately 'E.throw' any exception returned. -- -- Since 0.3.0@@ -483,108 +246,6 @@ runException_ :: ExceptionT Identity a -> a runException_ = runIdentity . runExceptionT_ -instance Monad m => Functor (ExceptionT m) where- fmap f = ExceptionT . (liftM . fmap) f . runExceptionT-instance Monad m => Applicative (ExceptionT m) where- pure = ExceptionT . return . Right- ExceptionT mf <*> ExceptionT ma = ExceptionT $ do- ef <- mf- case ef of- Left e -> return (Left e)- Right f -> do- ea <- ma- case ea of- Left e -> return (Left e)- Right x -> return (Right (f x))-instance Monad m => Monad (ExceptionT m) where- return = pure- ExceptionT ma >>= f = ExceptionT $ do- ea <- ma- case ea of- Left e -> return (Left e)- Right a -> runExceptionT (f a)-instance MonadBase b m => MonadBase b (ExceptionT m) where- liftBase = lift . liftBase-instance MonadTrans ExceptionT where- lift = ExceptionT . liftM Right-instance MonadTransControl ExceptionT where- newtype StT ExceptionT a = StExc { unStExc :: Either SomeException a }- liftWith f = ExceptionT $ liftM return $ f $ liftM StExc . runExceptionT- restoreT = ExceptionT . liftM unStExc-instance MonadBaseControl b m => MonadBaseControl b (ExceptionT m) where- newtype StM (ExceptionT m) a = StE { unStE :: ComposeSt ExceptionT m a }- liftBaseWith = defaultLiftBaseWith StE- restoreM = defaultRestoreM unStE--instance MonadCont m => MonadCont (ExceptionT m) where- callCC f = ExceptionT $- callCC $ \c ->- runExceptionT (f (\a -> ExceptionT $ c (Right a)))--instance MonadError e m => MonadError e (ExceptionT m) where- throwError = lift . throwError- catchError r h = ExceptionT $ runExceptionT r `catchError` (runExceptionT . h)--instance MonadRWS r w s m => MonadRWS r w s (ExceptionT m)--instance MonadReader r m => MonadReader r (ExceptionT m) where- ask = lift ask- local = mapExceptionT . local--mapExceptionT :: (m (Either SomeException a) -> n (Either SomeException b)) -> ExceptionT m a -> ExceptionT n b-mapExceptionT f = ExceptionT . f . runExceptionT--instance MonadState s m => MonadState s (ExceptionT m) where- get = lift get- put = lift . put--instance MonadWriter w m => MonadWriter w (ExceptionT m) where- tell = lift . tell- listen = mapExceptionT $ \ m -> do- (a, w) <- listen m- return $! fmap (\ r -> (r, w)) a- pass = mapExceptionT $ \ m -> pass $ do- a <- m- return $! case a of- Left l -> (Left l, id)- Right (r, f) -> (Right r, f)---- | A @Monad@ which can throw exceptions. Note that this does not work in a--- vanilla @ST@ or @Identity@ monad. Instead, you should use the 'ExceptionT'--- transformer in your stack if you are dealing with a non-@IO@ base monad.------ Since 0.3.0-class Monad m => MonadThrow m where- monadThrow :: E.Exception e => e -> m a--instance MonadThrow IO where- monadThrow = E.throwIO--instance MonadThrow Maybe where- monadThrow _ = Nothing-instance MonadThrow (Either SomeException) where- monadThrow = Left . E.toException-instance MonadThrow [] where- monadThrow _ = []--#define GO(T) instance (MonadThrow m) => MonadThrow (T m) where monadThrow = lift . monadThrow-#define GOX(X, T) instance (X, MonadThrow m) => MonadThrow (T m) where monadThrow = lift . monadThrow-GO(IdentityT)-GO(ListT)-GO(MaybeT)-GOX(Error e, ErrorT e)-GO(ReaderT r)-GO(ContT r)-GO(ResourceT)-GO(StateT s)-GOX(Monoid w, WriterT w)-GOX(Monoid w, RWST r w s)-GOX(Monoid w, Strict.RWST r w s)-GO(Strict.StateT s)-GOX(Monoid w, Strict.WriterT w)-#undef GO-#undef GOX- -- | Introduce a reference-counting scheme to allow a resource context to be -- shared by multiple threads. Once the last thread exits, all remaining -- resources will be released.@@ -612,24 +273,7 @@ (stateCleanup r) (restore $ f r)) --- | A @Monad@ based on some monad which allows running of some 'IO' actions,--- via unsafe calls. This applies to 'IO' and 'ST', for instance.------ Since 0.3.0-class Monad m => MonadUnsafeIO m where- unsafeLiftIO :: IO a -> m a -instance MonadUnsafeIO IO where- unsafeLiftIO = id--instance MonadUnsafeIO (ST s) where- unsafeLiftIO = unsafeIOToST--instance MonadUnsafeIO (Lazy.ST s) where- unsafeLiftIO = LazyUnsafe.unsafeIOToST--instance (MonadTrans t, MonadUnsafeIO m, Monad (t m)) => MonadUnsafeIO (t m) where- unsafeLiftIO = lift . unsafeLiftIO -- | Determine if some monad is still active. This is intended to prevent usage -- of a monadic state after it has been closed. This is necessary for such
+ Control/Monad/Trans/Resource/Internal.hs view
@@ -0,0 +1,420 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE UndecidableInstances #-}++module Control.Monad.Trans.Resource.Internal(+ ExceptionT(..)+ , InvalidAccess(..)+ , MonadResource(..)+ , MonadThrow(..)+ , MonadUnsafeIO(..)+ , ReleaseKey(..)+ , ReleaseMap(..)\+ , ResIO+ , ResourceT(..)+ , stateAlloc+ , stateCleanup+ , transResourceT+) where++import Control.Exception (throw,Exception,SomeException)+import Control.Applicative (Applicative (..))+import Control.Monad.Trans.Control+ ( MonadTransControl (..), MonadBaseControl (..)+ , ComposeSt, defaultLiftBaseWith, defaultRestoreM)+import Control.Monad.Base (MonadBase, liftBase)+import Control.Monad.Trans.Cont ( ContT )+import Control.Monad.Cont.Class ( MonadCont (..) )+import Control.Monad.Error.Class ( MonadError (..) )+import Control.Monad.RWS.Class ( MonadRWS )+import Control.Monad.Reader.Class ( MonadReader (..) )+import Control.Monad.State.Class ( MonadState (..) )+import Control.Monad.Writer.Class ( MonadWriter (..) )++import Control.Monad.Trans.Identity ( IdentityT)+import Control.Monad.Trans.List ( ListT )+import Control.Monad.Trans.Maybe ( MaybeT )+import Control.Monad.Trans.Error ( ErrorT, Error)+import Control.Monad.Trans.Reader ( ReaderT )+import Control.Monad.Trans.State ( StateT )+import Control.Monad.Trans.Writer ( WriterT )+import Control.Monad.Trans.RWS ( RWST )++import qualified Control.Monad.Trans.RWS.Strict as Strict ( RWST )+import qualified Control.Monad.Trans.State.Strict as Strict ( StateT )+import qualified Control.Monad.Trans.Writer.Strict as Strict ( WriterT )++import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad (liftM)+import qualified Control.Exception as E+import Control.Monad.ST (ST)+import Data.IntMap (IntMap)+import qualified Data.IntMap as IntMap+import qualified Data.IORef as I+import Data.Monoid+import Data.Typeable+import Data.Word(Word)++#if __GLASGOW_HASKELL__ >= 704+import Control.Monad.ST.Unsafe (unsafeIOToST)+#else+import Control.Monad.ST (unsafeIOToST)+#endif++#if __GLASGOW_HASKELL__ >= 704+import qualified Control.Monad.ST.Lazy.Unsafe as LazyUnsafe+#else+import qualified Control.Monad.ST.Lazy as LazyUnsafe+#endif++import qualified Control.Monad.ST.Lazy as Lazy++import Control.Monad.Morph++-- | A @Monad@ which allows for safe resource allocation. In theory, any monad+-- transformer stack included a @ResourceT@ can be an instance of+-- @MonadResource@.+--+-- Note: @runResourceT@ has a requirement for a @MonadBaseControl IO m@ monad,+-- which allows control operations to be lifted. A @MonadResource@ does not+-- have this requirement. This means that transformers such as @ContT@ can be+-- an instance of @MonadResource@. However, the @ContT@ wrapper will need to be+-- unwrapped before calling @runResourceT@.+--+-- Since 0.3.0+class (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource m where+ -- | Lift a @ResourceT IO@ action into the current @Monad@.+ --+ -- Since 0.4.0+ liftResourceT :: ResourceT IO a -> m a+++-- | A lookup key for a specific release action. This value is returned by+-- 'register' and 'allocate', and is passed to 'release'.+--+-- Since 0.3.0+data ReleaseKey = ReleaseKey !(I.IORef ReleaseMap) !Int+ deriving Typeable++type RefCount = Word+type NextKey = Int++data ReleaseMap =+ ReleaseMap !NextKey !RefCount !(IntMap (IO ()))+ | ReleaseMapClosed++-- | Convenient alias for @ResourceT IO@.+type ResIO a = ResourceT IO a+++instance MonadCont m => MonadCont (ResourceT m) where+ callCC f = ResourceT $ \i -> callCC $ \c -> unResourceT (f (ResourceT . const . c)) i++instance MonadError e m => MonadError e (ResourceT m) where+ throwError = lift . throwError+ catchError r h = ResourceT $ \i -> unResourceT r i `catchError` \e -> unResourceT (h e) i++instance MonadRWS r w s m => MonadRWS r w s (ResourceT m)++instance MonadReader r m => MonadReader r (ResourceT m) where+ ask = lift ask+ local = mapResourceT . local++mapResourceT :: (m a -> n b) -> ResourceT m a -> ResourceT n b+mapResourceT f = ResourceT . (f .) . unResourceT++instance MonadState s m => MonadState s (ResourceT m) where+ get = lift get+ put = lift . put++instance MonadWriter w m => MonadWriter w (ResourceT m) where+ tell = lift . tell+ listen = mapResourceT listen+ pass = mapResourceT pass++-- | A @Monad@ which can throw exceptions. Note that this does not work in a+-- vanilla @ST@ or @Identity@ monad. Instead, you should use the 'ExceptionT'+-- transformer in your stack if you are dealing with a non-@IO@ base monad.+--+-- Since 0.3.0+class Monad m => MonadThrow m where+ monadThrow :: E.Exception e => e -> m a++instance MonadThrow IO where+ monadThrow = E.throwIO++instance MonadThrow Maybe where+ monadThrow _ = Nothing+instance MonadThrow (Either SomeException) where+ monadThrow = Left . E.toException+instance MonadThrow [] where+ monadThrow _ = []++#define GO(T) instance (MonadThrow m) => MonadThrow (T m) where monadThrow = lift . monadThrow+#define GOX(X, T) instance (X, MonadThrow m) => MonadThrow (T m) where monadThrow = lift . monadThrow+GO(IdentityT)+GO(ListT)+GO(MaybeT)+GOX(Error e, ErrorT e)+GO(ReaderT r)+GO(ContT r)+GO(ResourceT)+GO(StateT s)+GOX(Monoid w, WriterT w)+GOX(Monoid w, RWST r w s)+GOX(Monoid w, Strict.RWST r w s)+GO(Strict.StateT s)+GOX(Monoid w, Strict.WriterT w)+#undef GO+#undef GOX++instance (MonadThrow m, MonadUnsafeIO m, MonadIO m, Applicative m) => MonadResource (ResourceT m) where+ liftResourceT = transResourceT liftIO++-- | Transform the monad a @ResourceT@ lives in. This is most often used to+-- strip or add new transformers to a stack, e.g. to run a @ReaderT@.+--+-- Note that this function is a slight generalization of 'hoist'.+--+-- Since 0.3.0+transResourceT :: (m a -> n b)+ -> ResourceT m a+ -> ResourceT n b+transResourceT f (ResourceT mx) = ResourceT (\r -> f (mx r))++-- | Since 0.4.7+instance MFunctor ResourceT where+ hoist f (ResourceT mx) = ResourceT (\r -> f (mx r))+-- | Since 0.4.7+instance MMonad ResourceT where+ embed f m = ResourceT (\i -> unResourceT (f (unResourceT m i)) i)++-- | The Resource transformer. This transformer keeps track of all registered+-- actions, and calls them upon exit (via 'runResourceT'). Actions may be+-- registered via 'register', or resources may be allocated atomically via+-- 'allocate'. @allocate@ corresponds closely to @bracket@.+--+-- Releasing may be performed before exit via the 'release' function. This is a+-- highly recommended optimization, as it will ensure that scarce resources are+-- freed early. Note that calling @release@ will deregister the action, so that+-- a release action will only ever be called once.+--+-- Since 0.3.0+newtype ResourceT m a = ResourceT { unResourceT :: I.IORef ReleaseMap -> m a }+#if __GLASGOW_HASKELL__ >= 707+ deriving Typeable+#else+instance Typeable1 m => Typeable1 (ResourceT m) where+ typeOf1 = goType undefined+ where+ goType :: Typeable1 m => m a -> ResourceT m a -> TypeRep+ goType m _ =+ mkTyConApp+#if __GLASGOW_HASKELL__ >= 704+ (mkTyCon3 "resourcet" "Control.Monad.Trans.Resource" "ResourceT")+#else+ (mkTyCon "Control.Monad.Trans.Resource.ResourceT")+#endif+ [ typeOf1 m+ ]+#endif++-- | Indicates either an error in the library, or misuse of it (e.g., a+-- @ResourceT@'s state is accessed after being released).+--+-- Since 0.3.0+data InvalidAccess = InvalidAccess { functionName :: String }+ deriving Typeable++instance Show InvalidAccess where+ show (InvalidAccess f) = concat+ [ "Control.Monad.Trans.Resource."+ , f+ , ": The mutable state is being accessed after cleanup. Please contact the maintainers."+ ]++instance Exception InvalidAccess++-------- All of our monad et al instances+instance Functor m => Functor (ResourceT m) where+ fmap f (ResourceT m) = ResourceT $ \r -> fmap f (m r)++instance Applicative m => Applicative (ResourceT m) where+ pure = ResourceT . const . pure+ ResourceT mf <*> ResourceT ma = ResourceT $ \r ->+ mf r <*> ma r++instance Monad m => Monad (ResourceT m) where+ return = ResourceT . const . return+ ResourceT ma >>= f = ResourceT $ \r -> do+ a <- ma r+ let ResourceT f' = f a+ f' r++instance MonadTrans ResourceT where+ lift = ResourceT . const++instance MonadIO m => MonadIO (ResourceT m) where+ liftIO = lift . liftIO++instance MonadBase b m => MonadBase b (ResourceT m) where+ liftBase = lift . liftBase++instance MonadTransControl ResourceT where+ newtype StT ResourceT a = StReader {unStReader :: a}+ liftWith f = ResourceT $ \r -> f $ \(ResourceT t) -> liftM StReader $ t r+ restoreT = ResourceT . const . liftM unStReader+ {-# INLINE liftWith #-}+ {-# INLINE restoreT #-}++instance MonadBaseControl b m => MonadBaseControl b (ResourceT m) where+ newtype StM (ResourceT m) a = StMT (StM m a)+ liftBaseWith f = ResourceT $ \reader' ->+ liftBaseWith $ \runInBase ->+ f $ liftM StMT . runInBase . (\(ResourceT r) -> r reader' )+ restoreM (StMT base) = ResourceT $ const $ restoreM base+instance Monad m => MonadThrow (ExceptionT m) where+ monadThrow = ExceptionT . return . Left . E.toException+instance MonadResource m => MonadResource (ExceptionT m) where+ liftResourceT = lift . liftResourceT+instance MonadIO m => MonadIO (ExceptionT m) where+ liftIO = lift . liftIO++#define GO(T) instance (MonadResource m) => MonadResource (T m) where liftResourceT = lift . liftResourceT+#define GOX(X, T) instance (X, MonadResource m) => MonadResource (T m) where liftResourceT = lift . liftResourceT+GO(IdentityT)+GO(ListT)+GO(MaybeT)+GOX(Error e, ErrorT e)+GO(ReaderT r)+GO(ContT r)+GO(StateT s)+GOX(Monoid w, WriterT w)+GOX(Monoid w, RWST r w s)+GOX(Monoid w, Strict.RWST r w s)+GO(Strict.StateT s)+GOX(Monoid w, Strict.WriterT w)+#undef GO+#undef GOX+++-- | The express purpose of this transformer is to allow non-@IO@-based monad+-- stacks to catch exceptions via the 'MonadThrow' typeclass.+--+-- Since 0.3.0+newtype ExceptionT m a = ExceptionT { runExceptionT :: m (Either SomeException a) }++stateAlloc :: I.IORef ReleaseMap -> IO ()+stateAlloc istate = do+ I.atomicModifyIORef istate $ \rm ->+ case rm of+ ReleaseMap nk rf m ->+ (ReleaseMap nk (rf + 1) m, ())+ ReleaseMapClosed -> throw $ InvalidAccess "stateAlloc"++stateCleanup :: I.IORef ReleaseMap -> IO ()+stateCleanup istate = E.mask_ $ do+ mm <- I.atomicModifyIORef istate $ \rm ->+ case rm of+ ReleaseMap nk rf m ->+ let rf' = rf - 1+ in if rf' == minBound+ then (ReleaseMapClosed, Just m)+ else (ReleaseMap nk rf' m, Nothing)+ ReleaseMapClosed -> throw $ InvalidAccess "stateCleanup"+ case mm of+ Just m ->+ mapM_ (\x -> try x >> return ()) $ IntMap.elems m+ Nothing -> return ()+ where+ try :: IO a -> IO (Either SomeException a)+ try = E.try+++-- | A @Monad@ based on some monad which allows running of some 'IO' actions,+-- via unsafe calls. This applies to 'IO' and 'ST', for instance.+--+-- Since 0.3.0+class Monad m => MonadUnsafeIO m where+ unsafeLiftIO :: IO a -> m a++instance MonadUnsafeIO IO where+ unsafeLiftIO = id++instance MonadUnsafeIO (ST s) where+ unsafeLiftIO = unsafeIOToST++instance MonadUnsafeIO (Lazy.ST s) where+ unsafeLiftIO = LazyUnsafe.unsafeIOToST++instance (MonadTrans t, MonadUnsafeIO m, Monad (t m)) => MonadUnsafeIO (t m) where+ unsafeLiftIO = lift . unsafeLiftIO++instance Monad m => Functor (ExceptionT m) where+ fmap f = ExceptionT . (liftM . fmap) f . runExceptionT+instance Monad m => Applicative (ExceptionT m) where+ pure = ExceptionT . return . Right+ ExceptionT mf <*> ExceptionT ma = ExceptionT $ do+ ef <- mf+ case ef of+ Left e -> return (Left e)+ Right f -> do+ ea <- ma+ case ea of+ Left e -> return (Left e)+ Right x -> return (Right (f x))+instance Monad m => Monad (ExceptionT m) where+ return = pure+ ExceptionT ma >>= f = ExceptionT $ do+ ea <- ma+ case ea of+ Left e -> return (Left e)+ Right a -> runExceptionT (f a)+instance MonadBase b m => MonadBase b (ExceptionT m) where+ liftBase = lift . liftBase+instance MonadTrans ExceptionT where+ lift = ExceptionT . liftM Right+instance MonadTransControl ExceptionT where+ newtype StT ExceptionT a = StExc { unStExc :: Either SomeException a }+ liftWith f = ExceptionT $ liftM return $ f $ liftM StExc . runExceptionT+ restoreT = ExceptionT . liftM unStExc+instance MonadBaseControl b m => MonadBaseControl b (ExceptionT m) where+ newtype StM (ExceptionT m) a = StE { unStE :: ComposeSt ExceptionT m a }+ liftBaseWith = defaultLiftBaseWith StE+ restoreM = defaultRestoreM unStE++instance MonadCont m => MonadCont (ExceptionT m) where+ callCC f = ExceptionT $+ callCC $ \c ->+ runExceptionT (f (\a -> ExceptionT $ c (Right a)))++instance MonadError e m => MonadError e (ExceptionT m) where+ throwError = lift . throwError+ catchError r h = ExceptionT $ runExceptionT r `catchError` (runExceptionT . h)++instance MonadRWS r w s m => MonadRWS r w s (ExceptionT m)++instance MonadReader r m => MonadReader r (ExceptionT m) where+ ask = lift ask+ local = mapExceptionT . local++mapExceptionT :: (m (Either SomeException a) -> n (Either SomeException b)) -> ExceptionT m a -> ExceptionT n b+mapExceptionT f = ExceptionT . f . runExceptionT++instance MonadState s m => MonadState s (ExceptionT m) where+ get = lift get+ put = lift . put++instance MonadWriter w m => MonadWriter w (ExceptionT m) where+ tell = lift . tell+ listen = mapExceptionT $ \ m -> do+ (a, w) <- listen m+ return $! fmap (\ r -> (r, w)) a+ pass = mapExceptionT $ \ m -> pass $ do+ a <- m+ return $! case a of+ Left l -> (Left l, id)+ Right (r, f) -> (Right r, f)
resourcet.cabal view
@@ -1,5 +1,5 @@ Name: resourcet-Version: 0.4.7.2+Version: 0.4.8 Synopsis: Deterministic allocation and freeing of scarce resources. Description: This package was originally included with the conduit package, and has since been split off. For more information, please see <http://www.yesodweb.com/book/conduits>.@@ -14,6 +14,7 @@ Library Exposed-modules: Control.Monad.Trans.Resource+ Control.Monad.Trans.Resource.Internal Build-depends: base >= 4.3 && < 5 , lifted-base >= 0.1 , transformers-base >= 0.4.1 && < 0.5