packages feed

monad-control 0.3.3.1 → 1.0.0.0

raw patch · 4 files changed

+613/−520 lines, 4 filesdep −transformers-compatdep ~basedep ~transformers-basePVP ok

version bump matches the API change (PVP)

Dependencies removed: transformers-compat

Dependency ranges changed: base, transformers-base

API changes (from Hackage documentation)

- Control.Monad.Trans.Control: instance MonadBaseControl b m => MonadBaseControl b (ExceptT e m)
- Control.Monad.Trans.Control: instance MonadTransControl (ExceptT e)
+ Control.Monad.Trans.Control: embed :: MonadBaseControl b m => (a -> m c) -> m (a -> b (StM m c))
+ Control.Monad.Trans.Control: embed_ :: MonadBaseControl b m => (a -> m ()) -> m (a -> b ())
+ Control.Monad.Trans.Control: liftBaseOpDiscard :: MonadBaseControl b m => ((a -> b ()) -> b c) -> (a -> m ()) -> m c
+ Control.Monad.Trans.Control: type RunInBaseDefault t m b = forall a. t m a -> b (ComposeSt t m a)
- Control.Monad.Trans.Control: class MonadBase b m => MonadBaseControl b m | m -> b where data family StM m :: * -> *
+ Control.Monad.Trans.Control: class MonadBase b m => MonadBaseControl b m | m -> b where type family StM m a :: *
- Control.Monad.Trans.Control: class MonadTrans t => MonadTransControl t where data family StT t :: * -> *
+ Control.Monad.Trans.Control: class MonadTrans t => MonadTransControl t where type family StT t a :: *
- Control.Monad.Trans.Control: defaultLiftBaseWith :: (MonadTransControl t, MonadBaseControl b m) => (forall c. ComposeSt t m c -> StM (t m) c) -> ((RunInBase (t m) b -> b a) -> t m a)
+ Control.Monad.Trans.Control: defaultLiftBaseWith :: (MonadTransControl t, MonadBaseControl b m) => (RunInBaseDefault t m b -> b a) -> t m a
- Control.Monad.Trans.Control: defaultLiftWith :: (Monad m, MonadTransControl n) => (forall b. n m b -> t m b) -> (forall o b. t o b -> n o b) -> (forall b. StT n b -> StT t b) -> (Run t -> m a) -> t m a
+ Control.Monad.Trans.Control: defaultLiftWith :: (Monad m, MonadTransControl n) => (forall b. n m b -> t m b) -> (forall o b. t o b -> n o b) -> (RunDefault t n -> m a) -> t m a
- Control.Monad.Trans.Control: defaultRestoreM :: (MonadTransControl t, MonadBaseControl b m) => (StM (t m) a -> ComposeSt t m a) -> (StM (t m) a -> t m a)
+ Control.Monad.Trans.Control: defaultRestoreM :: (MonadTransControl t, MonadBaseControl b m) => ComposeSt t m a -> t m a
- Control.Monad.Trans.Control: defaultRestoreT :: (Monad m, MonadTransControl n) => (n m a -> t m a) -> (StT t a -> StT n a) -> m (StT t a) -> t m a
+ Control.Monad.Trans.Control: defaultRestoreT :: (Monad m, MonadTransControl n) => (n m a -> t m a) -> m (StT n a) -> t m a
- Control.Monad.Trans.Control: type Run t = forall n b. Monad n => t n b -> n (StT t b)
+ Control.Monad.Trans.Control: type RunDefault t t' = forall n b. Monad n => t n b -> n (StT t' b)

Files

+ CHANGELOG view
@@ -0,0 +1,421 @@+1.0.0.0++* Switch the associated data types StT and StM to associated type synonyms.++  This is an API breaking change. To fix your MonadTransControl or+  MonadBaseControl instances simply remove the StT or StM constructors+  and deconstructors for your monad transformers or monad.++* Add the embed, embed_ and liftBaseOpDiscard functions.+++0.3.3.0++* Support transformers-0.4.0.0++* Drop unicode syntax and symbols+++0.3.2.3++*  Fix haddock documentation error+++0.3.2.2++*  Fix preprocessor directive for GHC 7.6.3+++0.3.2.1++* Resolve #14. Bump upper version bound of base to 5+++0.3.2++* Added defaultLiftWith and defaultRestoreT to simplify defining+  MonadTransControl for newtypes.+++0.3.1.4++* Compatibility with ghc head+++0.3.1.3++* Added a Trustworthy flag+++0.3.1.2++* Fix issue #9. Replace all Unicode in type variables.+++0.3.1.1++* Add MonadBaseControl instances for ST and STM.+++0.3++(Released on: Fri Dec 2 09:52:16 UTC 2011)++* Major new API which IMHO is easier to understand than the old one.++* On average about 60 times faster than the previous release!++* New package lifted-base providing lifted versions of functions from the base+  library. It exports the following modules:++  - Control.Exception.Lifted+  - Control.Concurrent.Lifted+  - Control.Concurrent.MVar.Lifted+  - System.Timeout.Lifted++  Not all modules from base are converted yet. If you need a lifted version of+  some function from base, just ask me to add it or send me a patch.+++0.2.0.3++(Released on: Sat Aug 27 21:18:22 UTC 2011)++* Fixed issue #2+  https://github.com/basvandijk/monad-control/issues/2+++0.2.0.2++(Released on: Mon Aug 8 09:16:08 UTC 2011)++* Switched to git on github.++* Tested with base-4.4 and ghc-7.2.1.++* Use the new cabal test-suite feature.+++0.2.0.1++(Released on: Wed Mar 16 15:53:50 UTC 2011)++* Added laws for MonadTransControl and MonadControlIO++* Bug fix: Add proper laziness to the MonadTransControl instances+  of the lazy StateT, WriteT and RWST+  These all failed the law: control $ \run -> run t = t+  where t = return undefined++* Add INLINABLE pragmas for most public functions+  A simple benchmark showed some functions+  (bracket and mask) improving by 30%.+++0.2++(Released on: Wed Feb 9 12:05:26 UTC 2011)++* Use RunInBase in the type of idLiftControl.++* Added this NEWS file.++* Only parameterize Run with t and use RankNTypes to quantify n and o+  -liftControl :: (Monad m, Monad n, Monad o) => (Run t n o -> m a) -> t m a+  +liftControl :: Monad m => (Run t -> m a) -> t m a++  -type Run t n o = forall b. t n b -> n (t o b)+  +type Run t = forall n o b. (Monad n, Monad o, Monad (t o)) => t n b -> n (t o b)++  Bumped version from 0.1 to 0.2 to indicate this breaking change in API.++* Added example of a derivation of liftControlIO.+  Really enlightening!+++0.1++(Released on: Sat Feb 5 23:36:21 UTC 2011)++* Initial release++This is the announcement message sent to the Haskell mailinglists:+http://www.mail-archive.com/haskell@haskell.org/msg23278.html+++Dear all,++Several attempts have been made to lift control operations (functions+that use monadic actions as input instead of just output) through+monad transformers:++MonadCatchIO-transformers[1] provided a type class that allowed to+overload some often used control operations (catch, block and+unblock). Unfortunately that library was limited to those operations.+It was not possible to use, say, alloca in a monad transformer. More+importantly however, the library was broken as was explained[2] by+Michael Snoyman. In response Michael created the MonadInvertIO type+class which solved the problems. Then Anders Kaseorg created the+monad-peel library which provided an even nicer implementation.++monad-control is a rewrite of monad-peel that uses CPS style+operations and exploits the RankNTypes language extension to simplify+and speedup most functions. A very preliminary and not yet fully+representative, benchmark shows that monad-control is on average about+2.6 times faster than monad-peel:++bracket:  2.4 x faster+bracket_: 3.1 x faster+catch:    1.8 x faster+try:      4.0 x faster+mask:     2.0 x faster++Note that, although the package comes with a test suite that passes, I+still consider it highly experimental.+++API DOCS:++http://hackage.haskell.org/package/monad-control+++INSTALLING:++$ cabal update+$ cabal install monad-control+++TESTING:++The package contains a copy of the monad-peel test suite written by+Anders. You can perform the tests using:++$ cabal unpack monad-control+$ cd monad-control+$ cabal configure -ftest+$ cabal test+++BENCHMARKING:++$ darcs get http://bifunctor.homelinux.net/~bas/bench-monad-peel-control/+$ cd bench-monad-peel-control+$ cabal configure+$ cabal build+$ dist/build/bench-monad-peel-control/bench-monad-peel-control+++DEVELOPING:++The darcs repository will be hosted on code.haskell.org ones that+server is back online. For the time being you can get the repository+from:++$ darcs get http://bifunctor.homelinux.net/~bas/monad-control/+++TUTORIAL:++This short unpolished tutorial will explain how to lift control+operations through monad transformers. Our goal is to lift a control+operation like:++foo ∷ M a → M a++where M is some monad, into a transformed monad like 'StateT M':++foo' ∷ StateT M a → StateT M a++The first thing we need to do is write an instance for the+MonadTransControl type class:++class MonadTrans t ⇒ MonadTransControl t where+  liftControl ∷ (Monad m, Monad n, Monad o)+              ⇒ (Run t n o → m a) → t m a++If you ignore the Run argument for now, you'll see that liftControl is+identical to the 'lift' method of the MonadTrans type class:++class MonadTrans t where+    lift ∷ Monad m ⇒ m a → t m a++So the instance for MonadTransControl will probably look very much+like the instance for MonadTrans. Let's see:++instance MonadTransControl (StateT s) where+    liftControl f = StateT $ \s → liftM (\x → (x, s)) (f run)++So what is this run function? Let's look at its type:++type Run t n o = ∀ b. t n b → n (t o b)++The run function executes a transformed monadic action 't n b' in the+non-transformed monad 'n'. In our case the 't' will be a StateT+computation. The only way to run a StateT computation is to give it+some state and the only state we have lying around is the one from the+outer computation: 's'. So let's run it on 's':++instance MonadTransControl (StateT s) where+    liftControl f =+        StateT $ \s →+          let run t = ... runStateT t s ...+          in liftM (\x → (x, s)) (f run)++Now that we are able to run a transformed monadic action, we're almost+done. Look at the type of Run again. The function should leave the+result 't o b' in the monad 'n'. This 't o b' computation should+contain the final state after running the supplied 't n b'+computation. In case of our StateT it should contain the final state+s':++instance MonadTransControl (StateT s) where+    liftControl f =+        StateT $ \s →+          let run t = liftM (\(x, s') → StateT $ \_ → return (x, s'))+                            (runStateT t s)+          in liftM (\x → (x, s)) (f run)++This final computation, "StateT $ \_ → return (x, s')", can later be+used to restore the final state. Now that we have our+MonadTransControl instance we can start using it. Recall that our goal+was to lift "foo ∷ M a → M a" into our StateT transformer yielding the+function "foo' ∷ StateT M a → StateT M a".++To define foo', the first thing we need to do is call liftControl:++foo' t = liftControl $ \run → ...++This captures the current state of the StateT computation and provides+us with the run function that allows us to run a StateT computation on+this captured state.++Now recall the type of liftControl ∷ (Run t n o → m a) → t m a. You+can see that in place of the ... we must fill in a value of type 'm+a'. In our case this will be a value of type 'M a'. We can construct+such a value by calling foo. However, foo expects an argument of type+'M a'. Fortunately we can provide one if we convert the supplied 't'+computation of type 'StateT M a' to 'M a' using our run function of+type ∀ b. StateT M b → M (StateT o b):++foo' t = ... liftControl $ \run → foo $ run t++However, note that the run function returns the final StateT+computation inside M. So the type of the right hand side is now+'StateT M (StateT o b)'. We would like to restore this final state. We+can do that using join:++foo' t = join $ liftControl $ \run → foo $ run t++That's it! Note that because it's so common to join after a+liftControl I provide an abstraction for it:++control = join ∘ liftControl++Allowing you to simplify foo' to:++foo' t = control $ \run → foo $ run t++Probably the most common control operations that you want to lift+through your transformers are IO operations. Think about: bracket,+alloca, mask, etc.. For this reason I provide the MonadControlIO type+class:++class MonadIO m ⇒ MonadControlIO m where+  liftControlIO ∷ (RunInBase m IO → IO a) → m a++Again, if you ignore the RunInBase argument, you will see that+liftControlIO is identical to the liftIO method of the MonadIO type+class:++class Monad m ⇒ MonadIO m where+    liftIO ∷ IO a → m a++Just like Run, RunInBase allows you to run your monadic computation+inside your base monad, which in case of liftControlIO is IO:++type RunInBase m base = ∀ b. m b → base (m b)++The instance for the base monad is trivial:++instance MonadControlIO IO where+    liftControlIO = idLiftControl++idLiftControl directly executes f and passes it a run function which+executes the given action and lifts the result r into the trivial+'return r' action:++idLiftControl ∷ Monad m ⇒ ((∀ b. m b → m (m b)) → m a) → m a+idLiftControl f = f $ liftM $ \r -> return r++The instances for the transformers are all identical. Let's look at+StateT and ReaderT:++instance MonadControlIO m ⇒ MonadControlIO (StateT s m) where+    liftControlIO = liftLiftControlBase liftControlIO++instance MonadControlIO m ⇒ MonadControlIO (ReaderT r m) where+    liftControlIO = liftLiftControlBase liftControlIO++The magic function is liftLiftControlBase. This function is used to+compose two liftControl operations, the outer provided by a+MonadTransControl instance and the inner provided as the argument:++liftLiftControlBase ∷ (MonadTransControl t, Monad base, Monad m, Monad (t m))+                    ⇒ ((RunInBase m     base → base a) →   m a)+                    → ((RunInBase (t m) base → base a) → t m a)+liftLiftControlBase lftCtrlBase =+  \f → liftControl $ \run →+         lftCtrlBase $ \runInBase →+           f $ liftM (join ∘ lift) ∘ runInBase ∘ run++Basically it captures the state of the outer monad transformer using+liftControl. Then it captures the state of the inner monad using the+supplied lftCtrlBase function. If you recall the identical definitions+of the liftControlIO methods: 'liftLiftControlBase liftControlIO' you+will see that this lftCtrlBase function is the recursive step of+liftLiftControlBase. If you use 'liftLiftControlBase liftControlIO' in+a stack of monad transformers a chain of liftControl operations is+created:++liftControl $ \run1 -> liftControl $ \run2 -> liftControl $ \run3 -> ...++This will recurse until we hit the base monad. Then+liftLiftControlBase will finally run f in the base monad supplying it+with a run function that is able to run a 't m a' computation in the+base monad. It does this by composing the run and runInBase functions.+Note that runInBase is basically the composition: '... ∘ run3 ∘ run2'.++However, just composing the run and runInBase functions is not enough.+Namely: runInBase ∘ run ∷ ∀ b. t m b → base (m (t m b)) while we need+to have ∀ b. t m b → base (t m b). So we need to lift the 'm (t m b)'+computation inside t yielding: 't m (t m b)' and then join that to get+'t m b'.++Now that we have our MonadControlIO instances we can start using them.+Let's look at how to lift 'bracket' into a monad supporting+MonadControlIO. Before we do that I define a little convenience+function similar to 'control':++controlIO = join ∘ liftControlIO++Bracket just calls controlIO which captures the state of m and+provides us with a runInIO function which allows us to run an m+computation in IO:++bracket ∷ MonadControlIO m+        ⇒ m a → (a → m b) → (a → m c) → m c+bracket before after thing =+  controlIO $ \runInIO →+    E.bracket (runInIO before)+              (\m → runInIO $ m >>= after)+              (\m → runInIO $ m >>= thing)++I welcome any comments, questions or patches.++Regards,++Bas++[1] http://hackage.haskell.org/package/MonadCatchIO-transformers+[2] http://docs.yesodweb.com/blog/invertible-monads-exceptions-allocations/+[3] http://hackage.haskell.org/package/monad-peel
Control/Monad/Trans/Control.hs view
@@ -31,21 +31,21 @@        -- ** Defaults for MonadTransControl       -- $MonadTransControlDefaults-    , defaultLiftWith, defaultRestoreT+    , RunDefault, defaultLiftWith, defaultRestoreT        -- * MonadBaseControl     , MonadBaseControl (..), RunInBase        -- ** Defaults for MonadBaseControl       -- $MonadBaseControlDefaults-    , ComposeSt, defaultLiftBaseWith, defaultRestoreM+    , ComposeSt, RunInBaseDefault, defaultLiftBaseWith, defaultRestoreM        -- * Utility functions-    , control+    , control, embed, embed_      , liftBaseOp, liftBaseOp_ -    , liftBaseDiscard+    , liftBaseDiscard, liftBaseOpDiscard     ) where  @@ -65,7 +65,7 @@ import GHC.Conc.Sync ( STM ) #endif -#if MIN_VERSION_base(4,4,0) || defined(INSTANCE_ST)+#if MIN_VERSION_base(4,4,0) import           Control.Monad.ST.Lazy             ( ST ) import qualified Control.Monad.ST.Strict as Strict ( ST ) #endif@@ -81,7 +81,10 @@ import Control.Monad.Trans.State    ( StateT   (StateT),    runStateT ) import Control.Monad.Trans.Writer   ( WriterT  (WriterT),   runWriterT ) import Control.Monad.Trans.RWS      ( RWST     (RWST),      runRWST )++#if MIN_VERSION_transformers(0,4,0) import Control.Monad.Trans.Except   ( ExceptT  (ExceptT),   runExceptT )+#endif  import qualified Control.Monad.Trans.RWS.Strict    as Strict ( RWST   (RWST),    runRWST ) import qualified Control.Monad.Trans.State.Strict  as Strict ( StateT (StateT),  runStateT )@@ -100,13 +103,15 @@ void = fmap (const ()) #endif +import Prelude (id)+ -------------------------------------------------------------------------------- -- MonadTransControl type class --------------------------------------------------------------------------------  class MonadTrans t => MonadTransControl t where   -- | Monadic state of @t@.-  data StT t :: * -> *+  type StT t a :: *    -- | @liftWith@ is similar to 'lift' in that it lifts a computation from   -- the argument monad to the constructed monad.@@ -145,9 +150,11 @@ --------------------------------------------------------------------------------  -- $MonadTransControlDefaults--- Following functions can be used to define 'MonadTransControl' instances for--- newtypes. --+-- The following functions can be used to define a 'MonadTransControl' instance+-- for a monad transformer which simply wraps another monad transformer which+-- already has a @MonadTransControl@ instance. For example:+-- -- @ -- {-\# LANGUAGE GeneralizedNewtypeDeriving \#-} --@@ -155,29 +162,31 @@ --   deriving (Monad, MonadTrans) -- -- instance MonadTransControl CounterT where---     newtype StT CounterT a = StCounter {unStCounter :: StT (StateT Int) a}---     liftWith = 'defaultLiftWith' CounterT unCounterT StCounter---     restoreT = 'defaultRestoreT' CounterT unStCounter+--     type StT CounterT a = StT (StateT Int) a+--     liftWith = 'defaultLiftWith' CounterT unCounterT+--     restoreT = 'defaultRestoreT' CounterT -- @ +-- | A function like 'Run' that runs a monad transformer @t@ which wraps the+-- monad transformer @t'@. This is used in 'defaultLiftWith'.+type RunDefault t t' = forall n b. Monad n => t n b -> n (StT t' b)+ -- | Default definition for the 'liftWith' method. defaultLiftWith :: (Monad m, MonadTransControl n)                 => (forall b.   n m b -> t m b)     -- ^ Monad constructor                 -> (forall o b. t o b -> n o b)     -- ^ Monad deconstructor-                -> (forall b.   StT n b -> StT t b) -- ^ 'StT' constructor-                -> (Run t -> m a)+                -> (RunDefault t n -> m a)                 -> t m a-defaultLiftWith t unT stT = \f -> t $ liftWith $ \run ->-                                        f $ liftM stT . run . unT-{-# INLINE defaultLiftWith #-}+defaultLiftWith t unT = \f -> t $ liftWith $ \run -> f $ run . unT+{-# INLINABLE defaultLiftWith #-} +-- | Default definition for the 'restoreT' method. defaultRestoreT :: (Monad m, MonadTransControl n)                 => (n m a -> t m a)     -- ^ Monad constructor-                -> (StT t a -> StT n a) -- ^ 'StT' deconstructor-                -> m (StT t a)+                -> m (StT n a)                 -> t m a-defaultRestoreT t unStT = t . restoreT . liftM unStT-{-# INLINE defaultRestoreT #-}+defaultRestoreT t = t . restoreT+{-# INLINABLE defaultRestoreT #-}   --------------------------------------------------------------------------------@@ -185,97 +194,99 @@ --------------------------------------------------------------------------------  instance MonadTransControl IdentityT where-    newtype StT IdentityT a = StId {unStId :: a}-    liftWith f = IdentityT $ f $ liftM StId . runIdentityT-    restoreT = IdentityT . liftM unStId-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+    type StT IdentityT a = a+    liftWith f = IdentityT $ f $ runIdentityT+    restoreT = IdentityT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance MonadTransControl MaybeT where-    newtype StT MaybeT a = StMaybe {unStMaybe :: Maybe a}-    liftWith f = MaybeT $ liftM return $ f $ liftM StMaybe . runMaybeT-    restoreT = MaybeT . liftM unStMaybe-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+    type StT MaybeT a = Maybe a+    liftWith f = MaybeT $ liftM return $ f $ runMaybeT+    restoreT = MaybeT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance Error e => MonadTransControl (ErrorT e) where-    newtype StT (ErrorT e) a = StError {unStError :: Either e a}-    liftWith f = ErrorT $ liftM return $ f $ liftM StError . runErrorT-    restoreT = ErrorT . liftM unStError-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+    type StT (ErrorT e) a = Either e a+    liftWith f = ErrorT $ liftM return $ f $ runErrorT+    restoreT = ErrorT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-} +#if MIN_VERSION_transformers(0,4,0) instance MonadTransControl (ExceptT e) where-    newtype StT (ExceptT e) a = StExcept {unStExcept :: Either e a}-    liftWith f = ExceptT $ liftM return $ f $ liftM StExcept . runExceptT-    restoreT = ExceptT . liftM unStExcept-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+    type StT (ExceptT e) a = Either e a+    liftWith f = ExceptT $ liftM return $ f $ runExceptT+    restoreT = ExceptT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}+#endif  instance MonadTransControl ListT where-    newtype StT ListT a = StList {unStList :: [a]}-    liftWith f = ListT $ liftM return $ f $ liftM StList . runListT-    restoreT = ListT . liftM unStList-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+    type StT ListT a = [a]+    liftWith f = ListT $ liftM return $ f $ runListT+    restoreT = ListT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance MonadTransControl (ReaderT r) where-    newtype StT (ReaderT r) a = StReader {unStReader :: a}-    liftWith f = ReaderT $ \r -> f $ \t -> liftM StReader $ runReaderT t r-    restoreT = ReaderT . const . liftM unStReader-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+    type StT (ReaderT r) a = a+    liftWith f = ReaderT $ \r -> f $ \t -> runReaderT t r+    restoreT = ReaderT . const+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance MonadTransControl (StateT s) where-    newtype StT (StateT s) a = StState {unStState :: (a, s)}+    type StT (StateT s) a = (a, s)     liftWith f = StateT $ \s ->                    liftM (\x -> (x, s))-                         (f $ \t -> liftM StState $ runStateT t s)-    restoreT = StateT . const . liftM unStState-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+                         (f $ \t -> runStateT t s)+    restoreT = StateT . const+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance MonadTransControl (Strict.StateT s) where-    newtype StT (Strict.StateT s) a = StState' {unStState' ::  (a, s)}+    type StT (Strict.StateT s) a = (a, s)     liftWith f = Strict.StateT $ \s ->                    liftM (\x -> (x, s))-                         (f $ \t -> liftM StState' $ Strict.runStateT t s)-    restoreT = Strict.StateT . const . liftM unStState'-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+                         (f $ \t -> Strict.runStateT t s)+    restoreT = Strict.StateT . const+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance Monoid w => MonadTransControl (WriterT w) where-    newtype StT (WriterT w) a = StWriter {unStWriter :: (a, w)}+    type StT (WriterT w) a = (a, w)     liftWith f = WriterT $ liftM (\x -> (x, mempty))-                                 (f $ liftM StWriter . runWriterT)-    restoreT = WriterT . liftM unStWriter-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+                                 (f $ runWriterT)+    restoreT = WriterT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance Monoid w => MonadTransControl (Strict.WriterT w) where-    newtype StT (Strict.WriterT w) a = StWriter' {unStWriter' :: (a, w)}+    type StT (Strict.WriterT w) a = (a, w)     liftWith f = Strict.WriterT $ liftM (\x -> (x, mempty))-                                        (f $ liftM StWriter' . Strict.runWriterT)-    restoreT = Strict.WriterT . liftM unStWriter'-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+                                        (f $ Strict.runWriterT)+    restoreT = Strict.WriterT+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance Monoid w => MonadTransControl (RWST r w s) where-    newtype StT (RWST r w s) a = StRWS {unStRWS :: (a, s, w)}+    type StT (RWST r w s) a = (a, s, w)     liftWith f = RWST $ \r s -> liftM (\x -> (x, s, mempty))-                                     (f $ \t -> liftM StRWS $ runRWST t r s)-    restoreT mSt = RWST $ \_ _ -> liftM unStRWS mSt-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+                                      (f $ \t -> runRWST t r s)+    restoreT mSt = RWST $ \_ _ -> mSt+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}  instance Monoid w => MonadTransControl (Strict.RWST r w s) where-    newtype StT (Strict.RWST r w s) a = StRWS' {unStRWS' ::  (a, s, w)}+    type StT (Strict.RWST r w s) a = (a, s, w)     liftWith f =         Strict.RWST $ \r s -> liftM (\x -> (x, s, mempty))-                                   (f $ \t -> liftM StRWS' $ Strict.runRWST t r s)-    restoreT mSt = Strict.RWST $ \_ _ -> liftM unStRWS' mSt-    {-# INLINE liftWith #-}-    {-# INLINE restoreT #-}+                                    (f $ \t -> Strict.runRWST t r s)+    restoreT mSt = Strict.RWST $ \_ _ -> mSt+    {-# INLINABLE liftWith #-}+    {-# INLINABLE restoreT #-}   --------------------------------------------------------------------------------@@ -284,7 +295,7 @@  class MonadBase b m => MonadBaseControl b m | m -> b where     -- | Monadic state of @m@.-    data StM m :: * -> *+    type StM m a :: *      -- | @liftBaseWith@ is similar to 'liftIO' and 'liftBase' in that it     -- lifts a base computation to the constructed monad.@@ -322,28 +333,28 @@ -- MonadBaseControl instances for all monads in the base library -------------------------------------------------------------------------------- -#define BASE(M, ST)                       \+#define BASE(M)                           \ instance MonadBaseControl (M) (M) where { \-    newtype StM (M) a = ST a;             \-    liftBaseWith f = f $ liftM ST;        \-    restoreM (ST x) = return x;           \-    {-# INLINE liftBaseWith #-};          \-    {-# INLINE restoreM #-}}+    type StM (M) a = a;                   \+    liftBaseWith f = f id;                \+    restoreM = return;                    \+    {-# INLINABLE liftBaseWith #-};       \+    {-# INLINABLE restoreM #-}} -BASE(IO,          StIO)-BASE(Maybe,       St)-BASE(Either e,    StE)-BASE([],          StL)-BASE((->) r,       StF)-BASE(Identity,    StI)+BASE(IO)+BASE(Maybe)+BASE(Either e)+BASE([])+BASE((->) r)+BASE(Identity)  #if MIN_VERSION_base(4,3,0)-BASE(STM,         StSTM)+BASE(STM) #endif -#if MIN_VERSION_base(4,4,0) || defined(INSTANCE_ST)-BASE(Strict.ST s, StSTS)-BASE(       ST s, StST)+#if MIN_VERSION_base(4,4,0)+BASE(Strict.ST s)+BASE(       ST s) #endif  #undef BASE@@ -360,18 +371,18 @@ -- -- @ -- instance MonadBaseControl b m => MonadBaseControl b (T m) where---     newtype StM (T m) a = StMT {unStMT :: 'ComposeSt' T m a}---     liftBaseWith = 'defaultLiftBaseWith' StMT---     restoreM     = 'defaultRestoreM'   unStMT+--     type StM (T m) a = 'ComposeSt' T m a+--     liftBaseWith     = 'defaultLiftBaseWith'+--     restoreM         = 'defaultRestoreM' -- @ -- -- Defining an instance for a base monad @B@ is equally straightforward: -- -- @ -- instance MonadBaseControl B B where---     newtype StM B a = StMB {unStMB :: a}---     liftBaseWith f  = f $ liftM  StMB---     restoreM        = return . unStMB+--     type StM B a   = a+--     liftBaseWith f = f 'id'+--     restoreM       = 'return' -- @  -- | Handy type synonym that composes the monadic states of @t@ and @m@.@@ -379,65 +390,70 @@ -- It can be used to define the 'StM' for new 'MonadBaseControl' instances. type ComposeSt t m a = StM m (StT t a) +-- | A function like 'RunInBase' that runs a monad transformer @t@ in its base+-- monad @b@. It is used in 'defaultLiftBaseWith'.+type RunInBaseDefault t m b = forall a. t m a -> b (ComposeSt t m a)+ -- | Default defintion for the 'liftBaseWith' method. -- -- Note that it composes a 'liftWith' of @t@ with a 'liftBaseWith' of @m@ to -- give a 'liftBaseWith' of @t m@: -- -- @--- defaultLiftBaseWith stM = \\f -> 'liftWith' $ \\run ->---                                   'liftBaseWith' $ \\runInBase ->---                                     f $ liftM stM . runInBase . run+-- defaultLiftBaseWith = \\f -> 'liftWith' $ \\run ->+--                               'liftBaseWith' $ \\runInBase ->+--                                 f $ runInBase . run -- @ defaultLiftBaseWith :: (MonadTransControl t, MonadBaseControl b m)-                    => (forall c. ComposeSt t m c -> StM (t m) c) -- ^ 'StM' constructor-                    -> ((RunInBase (t m) b  -> b a) -> t m a)-defaultLiftBaseWith stM = \f -> liftWith $ \run ->-                                  liftBaseWith $ \runInBase ->-                                    f $ liftM stM . runInBase . run-{-# INLINE defaultLiftBaseWith #-}+                    => (RunInBaseDefault t m b -> b a) -> t m a+defaultLiftBaseWith = \f -> liftWith $ \run ->+                              liftBaseWith $ \runInBase ->+                                f $ runInBase . run+{-# INLINABLE defaultLiftBaseWith #-}  -- | Default definition for the 'restoreM' method. ----- Note that: @defaultRestoreM unStM = 'restoreT' . 'restoreM' . unStM@+-- Note that: @defaultRestoreM = 'restoreT' . 'restoreM'@ defaultRestoreM :: (MonadTransControl t, MonadBaseControl b m)-                => (StM (t m) a -> ComposeSt t m a)  -- ^ 'StM' deconstructor-                -> (StM (t m) a -> t m a)-defaultRestoreM unStM = restoreT . restoreM . unStM-{-# INLINE defaultRestoreM #-}+                => ComposeSt t m a -> t m a+defaultRestoreM = restoreT . restoreM+{-# INLINABLE defaultRestoreM #-}   -------------------------------------------------------------------------------- -- MonadBaseControl transformer instances -------------------------------------------------------------------------------- -#define BODY(T, ST, unST) {                               \-    newtype StM (T m) a = ST {unST :: ComposeSt (T) m a}; \-    liftBaseWith = defaultLiftBaseWith ST;                \-    restoreM     = defaultRestoreM   unST;                \-    {-# INLINE liftBaseWith #-};                          \-    {-# INLINE restoreM #-}}+#define BODY(T) {                         \+    type StM (T m) a = ComposeSt (T) m a; \+    liftBaseWith = defaultLiftBaseWith;   \+    restoreM     = defaultRestoreM;       \+    {-# INLINABLE liftBaseWith #-};       \+    {-# INLINABLE restoreM #-}} -#define TRANS(         T, ST, unST) \-  instance (     MonadBaseControl b m) => MonadBaseControl b (T m) where BODY(T, ST, unST)-#define TRANS_CTX(CTX, T, ST, unST) \-  instance (CTX, MonadBaseControl b m) => MonadBaseControl b (T m) where BODY(T, ST, unST)+#define TRANS(         T) \+  instance (     MonadBaseControl b m) => MonadBaseControl b (T m) where BODY(T)+#define TRANS_CTX(CTX, T) \+  instance (CTX, MonadBaseControl b m) => MonadBaseControl b (T m) where BODY(T) -TRANS(IdentityT,       StMId,     unStMId)-TRANS(MaybeT,          StMMaybe,  unStMMaybe)-TRANS(ListT,           StMList,   unStMList)-TRANS(ReaderT r,       StMReader, unStMReader)-TRANS(Strict.StateT s, StMStateS, unStMStateS)-TRANS(       StateT s, StMState,  unStMState)-TRANS(ExceptT e,       StMExcept, unStMExcept)+TRANS(IdentityT)+TRANS(MaybeT)+TRANS(ListT)+TRANS(ReaderT r)+TRANS(Strict.StateT s)+TRANS(       StateT s) -TRANS_CTX(Error e,         ErrorT e,   StMError,   unStMError)-TRANS_CTX(Monoid w, Strict.WriterT w,  StMWriterS, unStMWriterS)-TRANS_CTX(Monoid w,        WriterT w,  StMWriter,  unStMWriter)-TRANS_CTX(Monoid w, Strict.RWST r w s, StMRWSS,    unStMRWSS)-TRANS_CTX(Monoid w,        RWST r w s, StMRWS,     unStMRWS)+#if MIN_VERSION_transformers(0,4,0)+TRANS(ExceptT e)+#endif +TRANS_CTX(Error e,         ErrorT e)+TRANS_CTX(Monoid w, Strict.WriterT w)+TRANS_CTX(Monoid w,        WriterT w)+TRANS_CTX(Monoid w, Strict.RWST r w s)+TRANS_CTX(Monoid w,        RWST r w s) + -------------------------------------------------------------------------------- -- * Utility functions --------------------------------------------------------------------------------@@ -445,8 +461,20 @@ -- | An often used composition: @control f = 'liftBaseWith' f >>= 'restoreM'@ control :: MonadBaseControl b m => (RunInBase m b -> b (StM m a)) -> m a control f = liftBaseWith f >>= restoreM-{-# INLINE control #-}+{-# INLINABLE control #-} +-- | Embed a transformer function as an function in the base monad returning a+-- mutated transformer state.+embed :: MonadBaseControl b m => (a -> m c) -> m (a -> b (StM m c))+embed f = liftBaseWith $ \runInBase -> return (runInBase . f)+{-# INLINABLE embed #-}++-- | Performs the same function as 'embed', but discards transformer state+-- from the embedded function.+embed_ :: MonadBaseControl b m => (a -> m ()) -> m (a -> b ())+embed_ f = liftBaseWith $ \runInBase -> return (void . runInBase . f)+{-# INLINABLE embed_ #-}+ -- | @liftBaseOp@ is a particular application of 'liftBaseWith' that allows -- lifting control operations of type: --@@ -459,7 +487,7 @@            => ((a -> b (StM m c)) -> b (StM m d))            -> ((a ->        m c)  ->        m d) liftBaseOp f = \g -> control $ \runInBase -> f $ runInBase . g-{-# INLINE liftBaseOp #-}+{-# INLINABLE liftBaseOp #-}  -- | @liftBaseOp_@ is a particular application of 'liftBaseWith' that allows -- lifting control operations of type:@@ -473,7 +501,7 @@             => (b (StM m a) -> b (StM m c))             -> (       m a  ->        m c) liftBaseOp_ f = \m -> control $ \runInBase -> f $ runInBase m-{-# INLINE liftBaseOp_ #-}+{-# INLINABLE liftBaseOp_ #-}  -- | @liftBaseDiscard@ is a particular application of 'liftBaseWith' that allows -- lifting control operations of type:@@ -489,4 +517,22 @@ -- @liftBaseDiscard forkIO :: 'MonadBaseControl' 'IO' m => m () -> m ThreadId@ liftBaseDiscard :: MonadBaseControl b m => (b () -> b a) -> (m () -> m a) liftBaseDiscard f = \m -> liftBaseWith $ \runInBase -> f $ void $ runInBase m-{-# INLINE liftBaseDiscard #-}+{-# INLINABLE liftBaseDiscard #-}++-- | @liftBaseOpDiscard@ is a particular application of 'liftBaseWith' that allows+-- lifting control operations of type:+--+-- @((a -> b ()) -> b c)@ to: @('MonadBaseControl' b m => (a -> m ()) -> m c)@.+--+-- Note that, while the argument computation @m ()@ has access to the captured+-- state, all its side-effects in @m@ are discarded. It is run only for its+-- side-effects in the base monad @b@.+--+-- For example:+--+-- @liftBaseDiscard (runServer addr port) :: 'MonadBaseControl' 'IO' m => m () -> m ()@+liftBaseOpDiscard :: MonadBaseControl b m+                  => ((a -> b ()) -> b c)+                  ->  (a -> m ()) -> m c+liftBaseOpDiscard f g = liftBaseWith $ \runInBase -> f $ void . runInBase . g+{-# INLINABLE liftBaseOpDiscard #-}
− NEWS
@@ -1,362 +0,0 @@-0.3--(Released on: Fri Dec 2 09:52:16 UTC 2011)--* Major new API which IMHO is easier to understand than the old one.--* On average about 60 times faster than the previous release!--* New package lifted-base providing lifted versions of functions from the base-  library. It exports the following modules:--  - Control.Exception.Lifted-  - Control.Concurrent.Lifted-  - Control.Concurrent.MVar.Lifted-  - System.Timeout.Lifted--  Not all modules from base are converted yet. If you need a lifted version of-  some function from base, just ask me to add it or send me a patch.---0.2.0.3--(Released on: Sat Aug 27 21:18:22 UTC 2011)--* Fixed issue #2-  https://github.com/basvandijk/monad-control/issues/2---0.2.0.2--(Released on: Mon Aug 8 09:16:08 UTC 2011)--* Switched to git on github.--* Tested with base-4.4 and ghc-7.2.1.--* Use the new cabal test-suite feature.---0.2.0.1--(Released on: Wed Mar 16 15:53:50 UTC 2011)--* Added laws for MonadTransControl and MonadControlIO--* Bug fix: Add proper laziness to the MonadTransControl instances-  of the lazy StateT, WriteT and RWST-  These all failed the law: control $ \run -> run t = t-  where t = return undefined--* Add INLINABLE pragmas for most public functions-  A simple benchmark showed some functions-  (bracket and mask) improving by 30%.---0.2--(Released on: Wed Feb 9 12:05:26 UTC 2011)--* Use RunInBase in the type of idLiftControl.--* Added this NEWS file.--* Only parameterize Run with t and use RankNTypes to quantify n and o-  -liftControl :: (Monad m, Monad n, Monad o) => (Run t n o -> m a) -> t m a-  +liftControl :: Monad m => (Run t -> m a) -> t m a--  -type Run t n o = forall b. t n b -> n (t o b)-  +type Run t = forall n o b. (Monad n, Monad o, Monad (t o)) => t n b -> n (t o b)--  Bumped version from 0.1 to 0.2 to indicate this breaking change in API.--* Added example of a derivation of liftControlIO.-  Really enlightening!---0.1--(Released on: Sat Feb 5 23:36:21 UTC 2011)--* Initial release--This is the announcement message sent to the Haskell mailinglists:-http://www.mail-archive.com/haskell@haskell.org/msg23278.html---Dear all,--Several attempts have been made to lift control operations (functions-that use monadic actions as input instead of just output) through-monad transformers:--MonadCatchIO-transformers[1] provided a type class that allowed to-overload some often used control operations (catch, block and-unblock). Unfortunately that library was limited to those operations.-It was not possible to use, say, alloca in a monad transformer. More-importantly however, the library was broken as was explained[2] by-Michael Snoyman. In response Michael created the MonadInvertIO type-class which solved the problems. Then Anders Kaseorg created the-monad-peel library which provided an even nicer implementation.--monad-control is a rewrite of monad-peel that uses CPS style-operations and exploits the RankNTypes language extension to simplify-and speedup most functions. A very preliminary and not yet fully-representative, benchmark shows that monad-control is on average about-2.6 times faster than monad-peel:--bracket:  2.4 x faster-bracket_: 3.1 x faster-catch:    1.8 x faster-try:      4.0 x faster-mask:     2.0 x faster--Note that, although the package comes with a test suite that passes, I-still consider it highly experimental.---API DOCS:--http://hackage.haskell.org/package/monad-control---INSTALLING:--$ cabal update-$ cabal install monad-control---TESTING:--The package contains a copy of the monad-peel test suite written by-Anders. You can perform the tests using:--$ cabal unpack monad-control-$ cd monad-control-$ cabal configure -ftest-$ cabal test---BENCHMARKING:--$ darcs get http://bifunctor.homelinux.net/~bas/bench-monad-peel-control/-$ cd bench-monad-peel-control-$ cabal configure-$ cabal build-$ dist/build/bench-monad-peel-control/bench-monad-peel-control---DEVELOPING:--The darcs repository will be hosted on code.haskell.org ones that-server is back online. For the time being you can get the repository-from:--$ darcs get http://bifunctor.homelinux.net/~bas/monad-control/---TUTORIAL:--This short unpolished tutorial will explain how to lift control-operations through monad transformers. Our goal is to lift a control-operation like:--foo ∷ M a → M a--where M is some monad, into a transformed monad like 'StateT M':--foo' ∷ StateT M a → StateT M a--The first thing we need to do is write an instance for the-MonadTransControl type class:--class MonadTrans t ⇒ MonadTransControl t where-  liftControl ∷ (Monad m, Monad n, Monad o)-              ⇒ (Run t n o → m a) → t m a--If you ignore the Run argument for now, you'll see that liftControl is-identical to the 'lift' method of the MonadTrans type class:--class MonadTrans t where-    lift ∷ Monad m ⇒ m a → t m a--So the instance for MonadTransControl will probably look very much-like the instance for MonadTrans. Let's see:--instance MonadTransControl (StateT s) where-    liftControl f = StateT $ \s → liftM (\x → (x, s)) (f run)--So what is this run function? Let's look at its type:--type Run t n o = ∀ b. t n b → n (t o b)--The run function executes a transformed monadic action 't n b' in the-non-transformed monad 'n'. In our case the 't' will be a StateT-computation. The only way to run a StateT computation is to give it-some state and the only state we have lying around is the one from the-outer computation: 's'. So let's run it on 's':--instance MonadTransControl (StateT s) where-    liftControl f =-        StateT $ \s →-          let run t = ... runStateT t s ...-          in liftM (\x → (x, s)) (f run)--Now that we are able to run a transformed monadic action, we're almost-done. Look at the type of Run again. The function should leave the-result 't o b' in the monad 'n'. This 't o b' computation should-contain the final state after running the supplied 't n b'-computation. In case of our StateT it should contain the final state-s':--instance MonadTransControl (StateT s) where-    liftControl f =-        StateT $ \s →-          let run t = liftM (\(x, s') → StateT $ \_ → return (x, s'))-                            (runStateT t s)-          in liftM (\x → (x, s)) (f run)--This final computation, "StateT $ \_ → return (x, s')", can later be-used to restore the final state. Now that we have our-MonadTransControl instance we can start using it. Recall that our goal-was to lift "foo ∷ M a → M a" into our StateT transformer yielding the-function "foo' ∷ StateT M a → StateT M a".--To define foo', the first thing we need to do is call liftControl:--foo' t = liftControl $ \run → ...--This captures the current state of the StateT computation and provides-us with the run function that allows us to run a StateT computation on-this captured state.--Now recall the type of liftControl ∷ (Run t n o → m a) → t m a. You-can see that in place of the ... we must fill in a value of type 'm-a'. In our case this will be a value of type 'M a'. We can construct-such a value by calling foo. However, foo expects an argument of type-'M a'. Fortunately we can provide one if we convert the supplied 't'-computation of type 'StateT M a' to 'M a' using our run function of-type ∀ b. StateT M b → M (StateT o b):--foo' t = ... liftControl $ \run → foo $ run t--However, note that the run function returns the final StateT-computation inside M. So the type of the right hand side is now-'StateT M (StateT o b)'. We would like to restore this final state. We-can do that using join:--foo' t = join $ liftControl $ \run → foo $ run t--That's it! Note that because it's so common to join after a-liftControl I provide an abstraction for it:--control = join ∘ liftControl--Allowing you to simplify foo' to:--foo' t = control $ \run → foo $ run t--Probably the most common control operations that you want to lift-through your transformers are IO operations. Think about: bracket,-alloca, mask, etc.. For this reason I provide the MonadControlIO type-class:--class MonadIO m ⇒ MonadControlIO m where-  liftControlIO ∷ (RunInBase m IO → IO a) → m a--Again, if you ignore the RunInBase argument, you will see that-liftControlIO is identical to the liftIO method of the MonadIO type-class:--class Monad m ⇒ MonadIO m where-    liftIO ∷ IO a → m a--Just like Run, RunInBase allows you to run your monadic computation-inside your base monad, which in case of liftControlIO is IO:--type RunInBase m base = ∀ b. m b → base (m b)--The instance for the base monad is trivial:--instance MonadControlIO IO where-    liftControlIO = idLiftControl--idLiftControl directly executes f and passes it a run function which-executes the given action and lifts the result r into the trivial-'return r' action:--idLiftControl ∷ Monad m ⇒ ((∀ b. m b → m (m b)) → m a) → m a-idLiftControl f = f $ liftM $ \r -> return r--The instances for the transformers are all identical. Let's look at-StateT and ReaderT:--instance MonadControlIO m ⇒ MonadControlIO (StateT s m) where-    liftControlIO = liftLiftControlBase liftControlIO--instance MonadControlIO m ⇒ MonadControlIO (ReaderT r m) where-    liftControlIO = liftLiftControlBase liftControlIO--The magic function is liftLiftControlBase. This function is used to-compose two liftControl operations, the outer provided by a-MonadTransControl instance and the inner provided as the argument:--liftLiftControlBase ∷ (MonadTransControl t, Monad base, Monad m, Monad (t m))-                    ⇒ ((RunInBase m     base → base a) →   m a)-                    → ((RunInBase (t m) base → base a) → t m a)-liftLiftControlBase lftCtrlBase =-  \f → liftControl $ \run →-         lftCtrlBase $ \runInBase →-           f $ liftM (join ∘ lift) ∘ runInBase ∘ run--Basically it captures the state of the outer monad transformer using-liftControl. Then it captures the state of the inner monad using the-supplied lftCtrlBase function. If you recall the identical definitions-of the liftControlIO methods: 'liftLiftControlBase liftControlIO' you-will see that this lftCtrlBase function is the recursive step of-liftLiftControlBase. If you use 'liftLiftControlBase liftControlIO' in-a stack of monad transformers a chain of liftControl operations is-created:--liftControl $ \run1 -> liftControl $ \run2 -> liftControl $ \run3 -> ...--This will recurse until we hit the base monad. Then-liftLiftControlBase will finally run f in the base monad supplying it-with a run function that is able to run a 't m a' computation in the-base monad. It does this by composing the run and runInBase functions.-Note that runInBase is basically the composition: '... ∘ run3 ∘ run2'.--However, just composing the run and runInBase functions is not enough.-Namely: runInBase ∘ run ∷ ∀ b. t m b → base (m (t m b)) while we need-to have ∀ b. t m b → base (t m b). So we need to lift the 'm (t m b)'-computation inside t yielding: 't m (t m b)' and then join that to get-'t m b'.--Now that we have our MonadControlIO instances we can start using them.-Let's look at how to lift 'bracket' into a monad supporting-MonadControlIO. Before we do that I define a little convenience-function similar to 'control':--controlIO = join ∘ liftControlIO--Bracket just calls controlIO which captures the state of m and-provides us with a runInIO function which allows us to run an m-computation in IO:--bracket ∷ MonadControlIO m-        ⇒ m a → (a → m b) → (a → m c) → m c-bracket before after thing =-  controlIO $ \runInIO →-    E.bracket (runInIO before)-              (\m → runInIO $ m >>= after)-              (\m → runInIO $ m >>= thing)--I welcome any comments, questions or patches.--Regards,--Bas--[1] http://hackage.haskell.org/package/MonadCatchIO-transformers-[2] http://docs.yesodweb.com/blog/invertible-monads-exceptions-allocations/-[3] http://hackage.haskell.org/package/monad-peel
monad-control.cabal view
@@ -1,5 +1,5 @@ Name:                monad-control-Version:             0.3.3.1+Version:             1.0.0.0 Synopsis:            Lift control operations, like exception catching, through monad transformers License:             BSD3 License-file:        LICENSE@@ -27,7 +27,7 @@   and exploits the @RankNTypes@ and @TypeFamilies@ language extensions to   simplify and speedup most definitions. -extra-source-files:  README.markdown, NEWS+extra-source-files:  README.markdown, CHANGELOG  -------------------------------------------------------------------------------- @@ -37,23 +37,11 @@  -------------------------------------------------------------------------------- -Flag instanceST-  Description:-    If enabled this package will export MonadBaseControl instances for the lazy-    and strict ST monad. If disabled these instances are only exported when base-    >= 4.4. If enabled it is required that the transformer-base package exports-    MonadBase instances for ST. It will do this by default.-  Default: True- Library-  if flag(instanceST)-    CPP-options: -DINSTANCE_ST-   Exposed-modules: Control.Monad.Trans.Control    Build-depends: base                 >= 3     && < 5                , transformers         >= 0.2   && < 0.5-               , transformers-base    >= 0.4.4 && < 0.5-               , transformers-compat  >= 0.3   && < 0.5+               , transformers-base    >= 0.4.2 && < 0.5    Ghc-options: -Wall