Hello community,
here is the log from the commit of package ghc-monad-control for openSUSE:Factory checked in at 2015-05-21 08:12:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-monad-control (Old)
and /work/SRC/openSUSE:Factory/.ghc-monad-control.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "ghc-monad-control"
Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-monad-control/ghc-monad-control.changes 2014-04-02 17:19:08.000000000 +0200
+++ /work/SRC/openSUSE:Factory/.ghc-monad-control.new/ghc-monad-control.changes 2015-05-21 08:12:59.000000000 +0200
@@ -1,0 +2,19 @@
+Tue Apr 21 19:32:20 UTC 2015 - mimi.vx@gmail.com
+
+- update to 1.0.0.4
+
+* Support transformers-compat-0.4.*.
+* Unconditionally add ExceptT instances using transformers-compat.
+ Courtesy of Adam Bergmark.
+* Add a base >= 4.5 constraint because monad-control only builds on GHC >= 7.4.
+* Use Safe instead of Trustworthy.
+ This requires a dependency on stm.
+* 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.
+* Support transformers-0.4.0.0
+* Drop unicode syntax and symbols
+
+-------------------------------------------------------------------
Old:
----
monad-control-0.3.2.1.tar.gz
New:
----
monad-control-1.0.0.4.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ ghc-monad-control.spec ++++++
--- /var/tmp/diff_new_pack.u8qCqQ/_old 2015-05-21 08:13:00.000000000 +0200
+++ /var/tmp/diff_new_pack.u8qCqQ/_new 2015-05-21 08:13:00.000000000 +0200
@@ -1,7 +1,7 @@
#
# spec file for package ghc-monad-control
#
-# Copyright (c) 2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
+# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -18,22 +18,23 @@
%global pkg_name monad-control
-Name: ghc-monad-control
-Version: 0.3.2.1
+Name: ghc-%{pkg_name}
+Version: 1.0.0.4
Release: 0
Summary: Lift control operations, like exception catching, through monad transformers
License: BSD-3-Clause
Group: System/Libraries
-Url: http://hackage.haskell.org/package/%{pkg_name}
-Source0: http://hackage.haskell.org/packages/archive/%{pkg_name}/%{version}/%{pkg_name}-%{version}.tar.gz
+Url: https://hackage.haskell.org/package/%{pkg_name}
+Source0: https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz
BuildRoot: %{_tmppath}/%{name}-%{version}-build
BuildRequires: ghc-Cabal-devel
BuildRequires: ghc-rpm-macros
# Begin cabal-rpm deps:
-BuildRequires: ghc-base-unicode-symbols-devel
+BuildRequires: ghc-stm-devel
BuildRequires: ghc-transformers-base-devel
+BuildRequires: ghc-transformers-compat-devel
BuildRequires: ghc-transformers-devel
# End cabal-rpm deps
@@ -53,18 +54,14 @@
exploits the 'RankNTypes' and 'TypeFamilies' language extensions to simplify
and speedup most definitions.
-The following 'criterion' based benchmark shows that 'monad-control' is on
-average about 99% faster than 'monad-peel':
-
-git clone https://github.com/basvandijk/bench-monad-peel-control.
-
%package devel
Summary: Haskell %{pkg_name} library development files
Group: Development/Libraries/Other
-Provides: %{name}-static = %{version}-%{release}
-Requires: %{name} = %{version}-%{release}
Requires: ghc-compiler = %{ghc_version}
+Requires(post): ghc-compiler = %{ghc_version}
+Requires(postun): ghc-compiler = %{ghc_version}
+Requires: %{name} = %{version}-%{release}
%description devel
This package provides the Haskell %{pkg_name} library development files.
++++++ monad-control-0.3.2.1.tar.gz -> monad-control-1.0.0.4.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/monad-control-0.3.2.1/CHANGELOG new/monad-control-1.0.0.4/CHANGELOG
--- old/monad-control-0.3.2.1/CHANGELOG 1970-01-01 01:00:00.000000000 +0100
+++ new/monad-control-1.0.0.4/CHANGELOG 2015-02-13 20:55:40.000000000 +0100
@@ -0,0 +1,444 @@
+1.0.0.4
+
+* Support transformers-compat-0.4.*.
+
+
+1.0.0.3
+
+* Unconditionally add ExceptT instances using transformers-compat.
+ Courtesy of Adam Bergmark.
+
+
+1.0.0.2
+
+* Add a base >= 4.5 constraint because monad-control only builds on GHC >= 7.4.
+
+
+1.0.0.1
+
+* Use Safe instead of Trustworthy.
+
+ This requires a dependency on stm.
+
+
+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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/monad-control-0.3.2.1/Control/Monad/Trans/Control.hs new/monad-control-1.0.0.4/Control/Monad/Trans/Control.hs
--- old/monad-control-0.3.2.1/Control/Monad/Trans/Control.hs 2013-04-23 18:40:21.000000000 +0200
+++ new/monad-control-1.0.0.4/Control/Monad/Trans/Control.hs 2015-02-13 20:55:40.000000000 +0100
@@ -1,16 +1,19 @@
{-# LANGUAGE CPP
- , UnicodeSyntax
, NoImplicitPrelude
, RankNTypes
, TypeFamilies
, FunctionalDependencies
, FlexibleInstances
, UndecidableInstances
- , MultiParamTypeClasses
- #-}
+ , MultiParamTypeClasses #-}
#if __GLASGOW_HASKELL__ >= 702
-{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE Safe #-}
+#endif
+
+#if MIN_VERSION_transformers(0,4,0)
+-- Hide warnings for the deprecated ErrorT transformer:
+{-# OPTIONS_GHC -fno-warn-warnings-deprecations #-}
#endif
{- |
@@ -20,13 +23,6 @@
Maintainer : Bas van Dijk
Stability : experimental
-
-(TODO: It would be nicer if the associated /data types/ 'StT' and 'StM' were
-associated /type synonyms/ instead. This would simplify a lot of code and could
-make some definitions more efficient because there'll be no need to wrap the
-monadic state in a data type. Unfortunately GHC has a bug which prevents this:
-http://hackage.haskell.org/trac/ghc/ticket/5595. I will switch to associated
-type synonyms when that bug is fixed.)
-}
module Control.Monad.Trans.Control
@@ -35,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
@@ -58,24 +54,20 @@
--------------------------------------------------------------------------------
-- from base:
-import Data.Function ( ($), const )
+import Data.Function ( (.), ($), const )
import Data.Monoid ( Monoid, mempty )
import Control.Monad ( Monad, (>>=), return, liftM )
import System.IO ( IO )
import Data.Maybe ( Maybe )
import Data.Either ( Either )
-#if MIN_VERSION_base(4,3,0)
-import GHC.Conc.Sync ( STM )
+#if MIN_VERSION_base(4,4,0)
+import Control.Monad.ST.Lazy.Safe ( ST )
+import qualified Control.Monad.ST.Safe as Strict ( ST )
#endif
-#if MIN_VERSION_base(4,4,0) || defined(INSTANCE_ST)
-import Control.Monad.ST.Lazy ( ST )
-import qualified Control.Monad.ST.Strict as Strict ( ST )
-#endif
-
--- from base-unicode-symbols:
-import Data.Function.Unicode ( (∘) )
+-- from stm:
+import Control.Monad.STM ( STM )
-- from transformers:
import Control.Monad.Trans.Class ( MonadTrans )
@@ -88,6 +80,7 @@
import Control.Monad.Trans.State ( StateT (StateT), runStateT )
import Control.Monad.Trans.Writer ( WriterT (WriterT), runWriterT )
import Control.Monad.Trans.RWS ( RWST (RWST), runRWST )
+import Control.Monad.Trans.Except ( ExceptT (ExceptT), runExceptT )
import qualified Control.Monad.Trans.RWS.Strict as Strict ( RWST (RWST), runRWST )
import qualified Control.Monad.Trans.State.Strict as Strict ( StateT (StateT), runStateT )
@@ -102,17 +95,19 @@
import Control.Monad ( void )
#else
import Data.Functor (Functor, fmap)
-void ∷ Functor f ⇒ f a → f ()
+void :: Functor f => f a -> f ()
void = fmap (const ())
#endif
+import Prelude (id)
+
--------------------------------------------------------------------------------
-- MonadTransControl type class
--------------------------------------------------------------------------------
-class MonadTrans t ⇒ MonadTransControl t where
+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.
@@ -127,7 +122,7 @@
-- @liftWith@ captures the state of @t@. It then provides the @m@
-- computation with a 'Run' function that allows running @t n@ computations in
-- @n@ (for all @n@) on the captured state.
- liftWith ∷ Monad m ⇒ (Run t → m a) → t m a
+ liftWith :: Monad m => (Run t -> m a) -> t m a
-- | Construct a @t@ computation from the monadic state of @t@ that is
-- returned from a 'Run' function.
@@ -135,7 +130,7 @@
-- Instances should satisfy:
--
-- @liftWith (\\run -> run t) >>= restoreT . return = t@
- restoreT ∷ Monad m ⇒ m (StT t a) → t m a
+ restoreT :: Monad m => m (StT t a) -> t m a
-- | A function that runs a transformed monad @t n@ on the monadic state that
-- was captured by 'liftWith'
@@ -143,7 +138,7 @@
-- A @Run t@ function yields a computation in @n@ that returns the monadic state
-- of @t@. This state can later be used to restore a @t@ computation using
-- 'restoreT'.
-type Run t = ∀ n b. Monad n ⇒ t n b → n (StT t b)
+type Run t = forall n b. Monad n => t n b -> n (StT t b)
--------------------------------------------------------------------------------
@@ -151,37 +146,43 @@
--------------------------------------------------------------------------------
-- $MonadTransControlDefaults
--- Following functions can be used to define 'MonadTransControl' instances for
--- newtypes.
--
--- @{-\# LANGUAGE GeneralizedNewtypeDeriving \#-}
+-- 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 \#-}
--
-- newtype CounterT m a = CounterT {unCounterT :: StateT Int m a}
-- 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)
- ⇒ (∀ b. n m b → t m b) -- ^ Monad constructor
- → (∀ o b. t o b → n o b) -- ^ Monad deconstructor
- → (∀ b. StT n b → StT t b) -- ^ 'StT' constructor
- → (Run t → m a)
- → t m a
-defaultLiftWith t unT stT = \f → t $ liftWith $ \run → f $ liftM stT ∘ run ∘ unT
-{-# INLINE defaultLiftWith #-}
-
-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)
- → t m a
-defaultRestoreT t unStT = t ∘ restoreT ∘ liftM unStT
-{-# INLINE defaultRestoreT #-}
+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
+ -> (RunDefault t n -> m a)
+ -> t m a
+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
+ -> m (StT n a)
+ -> t m a
+defaultRestoreT t = t . restoreT
+{-# INLINABLE defaultRestoreT #-}
--------------------------------------------------------------------------------
@@ -189,99 +190,106 @@
--------------------------------------------------------------------------------
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 #-}
-
-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 MaybeT a = Maybe a
+ liftWith f = MaybeT $ liftM return $ f $ runMaybeT
+ restoreT = MaybeT
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
+
+instance Error e => MonadTransControl (ErrorT e) where
+ type StT (ErrorT e) a = Either e a
+ liftWith f = ErrorT $ liftM return $ f $ runErrorT
+ restoreT = ErrorT
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
+
+instance MonadTransControl (ExceptT e) where
+ type StT (ExceptT e) a = Either e a
+ liftWith f = ExceptT $ liftM return $ f $ runExceptT
+ restoreT = ExceptT
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
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)}
- liftWith f = StateT $ \s →
- liftM (\x → (x, s))
- (f $ \t → liftM StState $ runStateT t s)
- restoreT = StateT ∘ const ∘ liftM unStState
- {-# INLINE liftWith #-}
- {-# INLINE restoreT #-}
+ type StT (StateT s) a = (a, s)
+ liftWith f = StateT $ \s ->
+ liftM (\x -> (x, s))
+ (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)}
- 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 #-}
-
-instance Monoid w ⇒ MonadTransControl (WriterT w) where
- newtype StT (WriterT w) a = StWriter {unStWriter ∷ (a, w)}
- liftWith f = WriterT $ liftM (\x → (x, mempty))
- (f $ liftM StWriter ∘ runWriterT)
- restoreT = WriterT ∘ liftM unStWriter
- {-# INLINE liftWith #-}
- {-# INLINE restoreT #-}
-
-instance Monoid w ⇒ MonadTransControl (Strict.WriterT w) where
- newtype StT (Strict.WriterT w) a = StWriter' {unStWriter' ∷ (a, w)}
- liftWith f = Strict.WriterT $ liftM (\x → (x, mempty))
- (f $ liftM StWriter' ∘ Strict.runWriterT)
- restoreT = Strict.WriterT ∘ liftM unStWriter'
- {-# INLINE liftWith #-}
- {-# INLINE restoreT #-}
-
-instance Monoid w ⇒ MonadTransControl (RWST r w s) where
- newtype StT (RWST r w s) a = StRWS {unStRWS ∷ (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 #-}
+ type StT (Strict.StateT s) a = (a, s)
+ liftWith f = Strict.StateT $ \s ->
+ liftM (\x -> (x, s))
+ (f $ \t -> Strict.runStateT t s)
+ restoreT = Strict.StateT . const
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
+
+instance Monoid w => MonadTransControl (WriterT w) where
+ type StT (WriterT w) a = (a, w)
+ liftWith f = WriterT $ liftM (\x -> (x, mempty))
+ (f $ runWriterT)
+ restoreT = WriterT
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
+
+instance Monoid w => MonadTransControl (Strict.WriterT w) where
+ type StT (Strict.WriterT w) a = (a, w)
+ liftWith f = Strict.WriterT $ liftM (\x -> (x, mempty))
+ (f $ Strict.runWriterT)
+ restoreT = Strict.WriterT
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
+
+instance Monoid w => MonadTransControl (RWST r w s) where
+ type StT (RWST r w s) a = (a, s, w)
+ liftWith f = RWST $ \r s -> liftM (\x -> (x, s, mempty))
+ (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)}
+instance Monoid w => MonadTransControl (Strict.RWST r w s) where
+ 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 #-}
+ Strict.RWST $ \r s -> liftM (\x -> (x, s, mempty))
+ (f $ \t -> Strict.runRWST t r s)
+ restoreT mSt = Strict.RWST $ \_ _ -> mSt
+ {-# INLINABLE liftWith #-}
+ {-# INLINABLE restoreT #-}
--------------------------------------------------------------------------------
-- MonadBaseControl type class
--------------------------------------------------------------------------------
-class MonadBase b m ⇒ MonadBaseControl b m | m → b where
+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.
@@ -296,7 +304,7 @@
-- @liftBaseWith@ captures the state of @m@. It then provides the base
-- computation with a 'RunInBase' function that allows running @m@
-- computations in the base monad on the captured state.
- liftBaseWith ∷ (RunInBase m b → b a) → m a
+ liftBaseWith :: (RunInBase m b -> b a) -> m a
-- | Construct a @m@ computation from the monadic state of @m@ that is
-- returned from a 'RunInBase' function.
@@ -304,7 +312,7 @@
-- Instances should satisfy:
--
-- @liftBaseWith (\\runInBase -> runInBase m) >>= restoreM = m@
- restoreM ∷ StM m a → m a
+ restoreM :: StM m a -> m a
-- | A function that runs a @m@ computation on the monadic state that was
-- captured by 'liftBaseWith'
@@ -312,35 +320,33 @@
-- A @RunInBase m@ function yields a computation in the base monad of @m@ that
-- returns the monadic state of @m@. This state can later be used to restore the
-- @m@ computation using 'restoreM'.
-type RunInBase m b = ∀ a. m a → b (StM m a)
+type RunInBase m b = forall a. m a -> b (StM m a)
--------------------------------------------------------------------------------
-- 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 #-}}
-
-BASE(IO, StIO)
-BASE(Maybe, St)
-BASE(Either e, StE)
-BASE([], StL)
-BASE((→) r, StF)
-BASE(Identity, StI)
-
-#if MIN_VERSION_base(4,3,0)
-BASE(STM, StSTM)
-#endif
-
-#if MIN_VERSION_base(4,4,0) || defined(INSTANCE_ST)
-BASE(Strict.ST s, StSTS)
-BASE( ST s, StST)
+ type StM (M) a = a; \
+ liftBaseWith f = f id; \
+ restoreM = return; \
+ {-# INLINABLE liftBaseWith #-}; \
+ {-# INLINABLE restoreM #-}}
+
+BASE(IO)
+BASE(Maybe)
+BASE(Either e)
+BASE([])
+BASE((->) r)
+BASE(Identity)
+
+BASE(STM)
+
+#if MIN_VERSION_base(4,4,0)
+BASE(Strict.ST s)
+BASE( ST s)
#endif
#undef BASE
@@ -357,18 +363,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@.
@@ -376,62 +382,65 @@
-- 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)
- ⇒ (∀ 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 #-}
+defaultLiftBaseWith :: (MonadTransControl t, MonadBaseControl b m)
+ => (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@
-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 #-}
+-- Note that: @defaultRestoreM = 'restoreT' . 'restoreM'@
+defaultRestoreM :: (MonadTransControl t, MonadBaseControl b m)
+ => 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 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)
-
-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_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)
+#define BODY(T) { \
+ type StM (T m) a = ComposeSt (T) m a; \
+ liftBaseWith = defaultLiftBaseWith; \
+ restoreM = defaultRestoreM; \
+ {-# INLINABLE liftBaseWith #-}; \
+ {-# INLINABLE restoreM #-}}
+
+#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)
+TRANS(MaybeT)
+TRANS(ListT)
+TRANS(ReaderT r)
+TRANS(Strict.StateT s)
+TRANS( StateT s)
+TRANS(ExceptT e)
+
+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)
--------------------------------------------------------------------------------
@@ -439,9 +448,21 @@
--------------------------------------------------------------------------------
-- | An often used composition: @control f = 'liftBaseWith' f >>= 'restoreM'@
-control ∷ MonadBaseControl b m ⇒ (RunInBase m b → b (StM m a)) → m a
+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:
@@ -451,11 +472,11 @@
-- For example:
--
-- @liftBaseOp alloca :: 'MonadBaseControl' 'IO' m => (Ptr a -> m c) -> m c@
-liftBaseOp ∷ MonadBaseControl b m
- ⇒ ((a → b (StM m c)) → b (StM m d))
- → ((a → m c) → m d)
-liftBaseOp f = \g → control $ \runInBase → f $ runInBase ∘ g
-{-# INLINE liftBaseOp #-}
+liftBaseOp :: MonadBaseControl b m
+ => ((a -> b (StM m c)) -> b (StM m d))
+ -> ((a -> m c) -> m d)
+liftBaseOp f = \g -> control $ \runInBase -> f $ runInBase . g
+{-# INLINABLE liftBaseOp #-}
-- | @liftBaseOp_@ is a particular application of 'liftBaseWith' that allows
-- lifting control operations of type:
@@ -465,11 +486,11 @@
-- For example:
--
-- @liftBaseOp_ mask_ :: 'MonadBaseControl' 'IO' m => m a -> m a@
-liftBaseOp_ ∷ MonadBaseControl b m
- ⇒ (b (StM m a) → b (StM m c))
- → ( m a → m c)
-liftBaseOp_ f = \m → control $ \runInBase → f $ runInBase m
-{-# INLINE liftBaseOp_ #-}
+liftBaseOp_ :: MonadBaseControl b m
+ => (b (StM m a) -> b (StM m c))
+ -> ( m a -> m c)
+liftBaseOp_ f = \m -> control $ \runInBase -> f $ runInBase m
+{-# INLINABLE liftBaseOp_ #-}
-- | @liftBaseDiscard@ is a particular application of 'liftBaseWith' that allows
-- lifting control operations of type:
@@ -483,6 +504,24 @@
-- For example:
--
-- @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 #-}
+liftBaseDiscard :: MonadBaseControl b m => (b () -> b a) -> (m () -> m a)
+liftBaseDiscard f = \m -> liftBaseWith $ \runInBase -> f $ void $ runInBase m
+{-# 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 #-}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/monad-control-0.3.2.1/NEWS new/monad-control-1.0.0.4/NEWS
--- old/monad-control-0.3.2.1/NEWS 2013-04-23 18:40:21.000000000 +0200
+++ new/monad-control-1.0.0.4/NEWS 1970-01-01 01:00:00.000000000 +0100
@@ -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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/monad-control-0.3.2.1/README.markdown new/monad-control-1.0.0.4/README.markdown
--- old/monad-control-0.3.2.1/README.markdown 2013-04-23 18:40:21.000000000 +0200
+++ new/monad-control-1.0.0.4/README.markdown 2015-02-13 20:55:40.000000000 +0100
@@ -12,6 +12,6 @@
The package includes a copy of the `monad-peel` testsuite written by
Anders Kaseorg The tests can be performed by using `cabal test`.
-[This `critertion`](https://github.com/basvandijk/bench-monad-peel-control)
+[This `criterion`](https://github.com/basvandijk/bench-monad-peel-control)
based benchmark shows that `monad-control` is on average about 2.5
times faster than `monad-peel`.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/monad-control-0.3.2.1/monad-control.cabal new/monad-control-1.0.0.4/monad-control.cabal
--- old/monad-control-0.3.2.1/monad-control.cabal 2013-04-23 18:40:21.000000000 +0200
+++ new/monad-control-1.0.0.4/monad-control.cabal 2015-02-13 20:55:40.000000000 +0100
@@ -1,5 +1,5 @@
Name: monad-control
-Version: 0.3.2.1
+Version: 1.0.0.4
Synopsis: Lift control operations, like exception catching, through monad transformers
License: BSD3
License-file: LICENSE
@@ -26,13 +26,8 @@
library. The main difference is that this package provides CPS style operators
and exploits the @RankNTypes@ and @TypeFamilies@ language extensions to
simplify and speedup most definitions.
- .
- The following @criterion@ based benchmark shows that @monad-control@ is on
- average about 99% faster than @monad-peel@:
- .
- @git clone https://github.com/basvandijk/bench-monad-peel-control@
-extra-source-files: README.markdown, NEWS
+extra-source-files: README.markdown, CHANGELOG
--------------------------------------------------------------------------------
@@ -42,23 +37,13 @@
--------------------------------------------------------------------------------
-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
- , base-unicode-symbols >= 0.1.1 && < 0.3
- , transformers >= 0.2 && < 0.4
- , transformers-base >= 0.4.1 && < 0.5
+ Build-depends: base >= 4.5 && < 5
+ , stm >= 2.3 && < 3
+ , transformers >= 0.2 && < 0.5
+ , transformers-compat >= 0.3 && < 0.5
+ , transformers-base >= 0.4.4 && < 0.5
Ghc-options: -Wall