monad-unlift 0.1.0.0 → 0.1.0.1
raw patch · 6 files changed
+110/−8 lines, 6 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
Files
- Control/Monad/Trans/RWS/Ref.hs +4/−0
- Control/Monad/Trans/State/Ref.hs +4/−0
- Control/Monad/Trans/Unlift.hs +1/−5
- Control/Monad/Trans/Writer/Ref.hs +4/−0
- README.md +96/−2
- monad-unlift.cabal +1/−1
Control/Monad/Trans/RWS/Ref.hs view
@@ -11,6 +11,10 @@ -- transformers in the transformers package is that it does not have space -- leaks in the writer component. For more information, see -- <https://mail.haskell.org/pipermail/libraries/2012-October/018599.html>.+--+-- Please see the documentation at+-- <https://www.stackage.org/package/monad-unlift> for more details on using+-- this module. module Control.Monad.Trans.RWS.Ref ( RWSRefT , runRWSRefT
Control/Monad/Trans/State/Ref.hs view
@@ -6,6 +6,10 @@ {-# LANGUAGE UndecidableInstances #-} -- | An implementation of @StateT@ built on top of mutable references, -- providing a proper monad morphism.+--+-- Please see the documentation at+-- <https://www.stackage.org/package/monad-unlift> for more details on using+-- this module. module Control.Monad.Trans.State.Ref ( StateRefT , runStateRefT
Control/Monad/Trans/Unlift.hs view
@@ -27,17 +27,13 @@ , MonadBaseControl (..) ) where -import Control.Monad (ap, liftM)+import Control.Monad (liftM) import Control.Monad.Base (MonadBase (..))-import Control.Monad.ST (ST)-import Control.Monad.STM (STM) import Control.Monad.Trans.Class (MonadTrans (..)) import Control.Monad.Trans.Control (MonadBaseControl (..), MonadTransControl (..))-import Control.Monad.Trans.Reader (ReaderT) import Data.Constraint ((:-), (\\)) import Data.Constraint.Forall (Forall, inst)-import Data.Functor.Identity (Identity) -- | A function which can move an action down the monad transformer stack, by -- providing any necessary environment to the action.
Control/Monad/Trans/Writer/Ref.hs view
@@ -11,6 +11,10 @@ -- transformers in the transformers package is that it does not have space -- leaks. For more information, see -- <https://mail.haskell.org/pipermail/libraries/2012-October/018599.html>.+--+-- Please see the documentation at+-- <https://www.stackage.org/package/monad-unlift> for more details on using+-- this module. module Control.Monad.Trans.Writer.Ref ( WriterRefT , runWriterRefT
README.md view
@@ -1,5 +1,71 @@ ## monad-unlift +Typeclasses for providing for unlifting of monad transformers and stacks, and+concrete implementations of common transformers implementing this type classes.++## Synopsis++```haskell+import Control.Concurrent.Async+import Control.Monad.Trans.Unlift+import Control.Monad.Trans.RWS.Ref+import Control.Monad.IO.Class+import Data.Mutable++-- Some artbirary data type for the MonadReader+data SomeEnv = SomeEnv Int++myFunc :: RWSRefT+ -- The WriterT piece is contained by an IORef+ IORef+ -- For efficiency, we store the state in a primitive+ -- reference for efficiency+ (PRef RealWorld)+ SomeEnv -- Reader+ [String] -- Writer+ Int -- State+ IO+ (String, String)+myFunc = do+ -- Get the unlift function. Due to weaknesses in ImpredicativeTypes, we+ -- need to use a newtype wrapper. You can also use askRunBase.+ --+ -- If you want to just unwrap one transformer layer, use+ -- askUnlift/askRun/Unlift.+ UnliftBase run <- askUnliftBase++ -- Note that we can use unlift to turn our transformer actions into IO+ -- actions. Unlike the standard RWST, actions from separate threads are+ -- both retained due to mutable references.+ --+ -- In real life: you shouldn't rely on this working, as RWST is not thread+ -- safe. This example is provided as a good demonstration of the type level+ -- functionality.+ liftIO $ concurrently (run foo) (run bar)+ where+ foo = do+ tell ["starting foo"]+ modify (+ 1)+ tell ["leaving foo"]+ return "foo is done"+ bar = do+ tell ["starting bar"]+ SomeEnv e <- ask+ modify (+ e)+ tell ["leaving bar"]+ return "bar is done"++main :: IO ()+main = do+ ((w, x), y, z) <- runRWSRefT myFunc (SomeEnv 5) 6+ print w -- foo is done+ print x -- bar is done+ print y -- 12 = 6 + 5 + 1+ print z -- starting and leaving statements, order ambiguous+```++## Overview+ A common pattern is to have some kind of a monad transformer, and want to pass an action into a function that requires actions in a base monad. That sounds a bit abstract, so let's give a concrete example:@@ -65,7 +131,7 @@ ``` Notice how we get `(a, b)` in the return type as desired. There's no need to-unwrap values are deal with context.+unwrap values or deal with context. ### MonadTransUnlift @@ -74,7 +140,7 @@ later. Some interesting cases in this space are: * `IdentityT` and things isomorphic to it; in this case, you can think of the environment as being `()`-* Transformers which contain a mutable reference in their environment. This allows them to behave like stateful transformers (e.g., `StateT` or `WriterT`), but still behave the monad morphism laws. (See below for more details.)+* Transformers which contain a mutable reference in their environment. This allows them to behave like stateful transformers (e.g., `StateT` or `WriterT`), but still obey the monad morphism laws. (See below for more details.) Due to weaknesses in GHC's ImpredicativeTypes, we have a helper datatype to allow for getting polymorphic unlift functions, appropriately named `Unlift`.@@ -138,6 +204,15 @@ package, which allows you to have highly efficient references like `PRef` instead of always using boxed references like `IORef`. +Note that, for generality, the reference transformers take type parameters+indicating which mutable reference type to use. Some examples you may use are:++* `IORef` for boxed references in `IO`+* `STRef s` for boxed references in `ST`+* `PRef RealWorld` for an unboxed reference in `IO`++See the synopsis for a complete example.+ ### conduit The `transPipe` function in conduit has caused confusion in the past due to its@@ -150,3 +225,22 @@ valid monad morphisms. `HandlerT` is in fact my first example of using the "enviornment holding a mutable reference" technique to overcome exceptions destroying state.++```haskell+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+import Control.Concurrent.Async+import Control.Monad.IO.Class+import Control.Monad.Logger+import Control.Monad.Trans.Unlift++main :: IO ()+main = runStdoutLoggingT foo++foo :: (MonadLogger m, MonadBaseUnlift IO m, MonadIO m) => m ()+foo = do+ run <- askRunBase+ a <- liftIO $ async $ run $ $logDebug "Hello World!"+ liftIO $ wait a+```
monad-unlift.cabal view
@@ -1,5 +1,5 @@ name: monad-unlift-version: 0.1.0.0+version: 0.1.0.1 synopsis: Typeclasses for representing monad transformer unlifting description: See README.md homepage: https://github.com/fpco/monad-unlift