unliftio-core 0.1.1.0 → 0.2.1.0
raw patch · 3 files changed
Files
- ChangeLog.md +22/−0
- src/Control/Monad/IO/Unlift.hs +85/−35
- unliftio-core.cabal +11/−13
ChangeLog.md view
@@ -1,3 +1,25 @@+# ChangeLog for unliftio-core++## 0.2.1.0++* Added `Control.Monad.IO.Unlift.liftIOOp`++## 0.2.0.2++* Widen `base` upperbound to `< 4.17` to support ghc-9.2.++## 0.2.0.1++* Remove faulty default implementation of `withRunInIO` [#56](https://github.com/fpco/unliftio/issues/56)++## 0.2.0.0++* Move `askUnliftIO` out of class [#55](https://github.com/fpco/unliftio/issues/55)++## 0.1.2.0++* Add `wrappedWithRunInIO`.+ ## 0.1.1.0 * Doc improvements.
src/Control/Monad/IO/Unlift.hs view
@@ -4,13 +4,15 @@ module Control.Monad.IO.Unlift ( MonadUnliftIO (..) , UnliftIO (..)+ , askUnliftIO , askRunInIO , withUnliftIO , toIO+ , wrappedWithRunInIO+ , liftIOOp , MonadIO (..) ) where -import Control.Monad (liftM) import Control.Monad.IO.Class import Control.Monad.Trans.Reader (ReaderT (..)) import Control.Monad.Trans.Identity (IdentityT (..))@@ -34,54 +36,45 @@ -- 'MonadUnliftIO' to 'ReaderT' and 'IdentityT' transformers on top of -- 'IO'. ----- Laws. For any value @u@ returned by 'askUnliftIO', it must meet the+-- Laws. For any function @run@ provided by 'withRunInIO', it must meet the -- monad transformer laws as reformulated for @MonadUnliftIO@: ----- * @unliftIO u . return = return@+-- * @run . return = return@ ----- * @unliftIO u (m >>= f) = unliftIO u m >>= unliftIO u . f@+-- * @run (m >>= f) = run m >>= run . f@ ----- The third is a currently nameless law which ensures that the--- current context is preserved.+-- Instances of @MonadUnliftIO@ must also satisfy the following laws: ----- * @askUnliftIO >>= (\u -> liftIO (unliftIO u m)) = m@+-- [Identity law] @withRunInIO (\\run -> run m) = m@+-- [Inverse law] @withRunInIO (\\_ -> m) = liftIO m@ ----- If you have a name for this, please submit it in a pull request for--- great glory.+-- As an example of an invalid instance, a naive implementation of+-- @MonadUnliftIO (StateT s m)@ might be --+-- @+-- withRunInIO inner =+-- StateT $ \\s ->+-- withRunInIO $ \\run ->+-- inner (run . flip evalStateT s)+-- @+--+-- This breaks the identity law because the inner @run m@ would throw away+-- any state changes in @m@.+-- -- @since 0.1.0.0 class MonadIO m => MonadUnliftIO m where- {-# MINIMAL askUnliftIO | withRunInIO #-}- -- | Capture the current monadic context, providing the ability to- -- run monadic actions in 'IO'.- --- -- See 'UnliftIO' for an explanation of why we need a helper- -- datatype here.- -- @since 0.1.0.0- askUnliftIO :: m (UnliftIO m)- askUnliftIO = withRunInIO (\run -> return (UnliftIO run))- {-# INLINE askUnliftIO #-}- -- Would be better, but GHC hates us- -- askUnliftIO :: m (forall a. m a -> IO a)- -- | Convenience function for capturing the monadic context and running an 'IO' -- action with a runner function. The runner function is used to run a monadic -- action @m@ in @IO@. -- -- @since 0.1.0.0- {-# INLINE withRunInIO #-} withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b- withRunInIO inner = askUnliftIO >>= \u -> liftIO (inner (unliftIO u))+ instance MonadUnliftIO IO where- {-# INLINE askUnliftIO #-}- askUnliftIO = return (UnliftIO id) {-# INLINE withRunInIO #-} withRunInIO inner = inner id+ instance MonadUnliftIO m => MonadUnliftIO (ReaderT r m) where- {-# INLINE askUnliftIO #-}- askUnliftIO = ReaderT $ \r ->- withUnliftIO $ \u ->- return (UnliftIO (unliftIO u . flip runReaderT r)) {-# INLINE withRunInIO #-} withRunInIO inner = ReaderT $ \r ->@@ -89,17 +82,31 @@ inner (run . flip runReaderT r) instance MonadUnliftIO m => MonadUnliftIO (IdentityT m) where- {-# INLINE askUnliftIO #-}- askUnliftIO = IdentityT $- withUnliftIO $ \u ->- return (UnliftIO (unliftIO u . runIdentityT)) {-# INLINE withRunInIO #-} withRunInIO inner = IdentityT $ withRunInIO $ \run -> inner (run . runIdentityT) --- | Same ask 'askUnliftIO', but returns a monomorphic function+-- | Capture the current monadic context, providing the ability to+-- run monadic actions in 'IO'.+--+-- See 'UnliftIO' for an explanation of why we need a helper+-- datatype here.+--+-- Prior to version 0.2.0.0 of this library, this was a method in the+-- 'MonadUnliftIO' type class. It was moved out due to+-- <https://github.com/fpco/unliftio/issues/55>.+--+-- @since 0.1.0.0+askUnliftIO :: MonadUnliftIO m => m (UnliftIO m)+askUnliftIO = withRunInIO (\run -> return (UnliftIO run))+{-# INLINE askUnliftIO #-}+-- Would be better, but GHC hates us+-- askUnliftIO :: m (forall a. m a -> IO a)+++-- | Same as 'askUnliftIO', but returns a monomorphic function -- instead of a polymorphic newtype wrapper. If you only need to apply -- the transformation on one concrete type, this function can be more -- convenient.@@ -125,3 +132,46 @@ {-# INLINE toIO #-} toIO :: MonadUnliftIO m => m a -> m (IO a) toIO m = withRunInIO $ \run -> return $ run m++{- | A helper function for implementing @MonadUnliftIO@ instances.+Useful for the common case where you want to simply delegate to the+underlying transformer.++Note: You can derive 'MonadUnliftIO' for newtypes without this helper function+in @unliftio-core@ 0.2.0.0 and later.++@since 0.1.2.0+==== __Example__++> newtype AppT m a = AppT { unAppT :: ReaderT Int (ResourceT m) a }+> deriving (Functor, Applicative, Monad, MonadIO)+>+> -- Same as `deriving newtype (MonadUnliftIO)`+> instance MonadUnliftIO m => MonadUnliftIO (AppT m) where+> withRunInIO = wrappedWithRunInIO AppT unAppT+-}+{-# INLINE wrappedWithRunInIO #-}+wrappedWithRunInIO :: MonadUnliftIO n+ => (n b -> m b)+ -- ^ The wrapper, for instance @IdentityT@.+ -> (forall a. m a -> n a)+ -- ^ The inverse, for instance @runIdentityT@.+ -> ((forall a. m a -> IO a) -> IO b)+ -- ^ The actual function to invoke 'withRunInIO' with.+ -> m b+wrappedWithRunInIO wrap unwrap inner = wrap $ withRunInIO $ \run ->+ inner $ run . unwrap++{- | A helper function for lifting @IO a -> IO b@ functions into any @MonadUnliftIO@.++=== __Example__++> liftedTry :: (Exception e, MonadUnliftIO m) => m a -> m (Either e a)+> liftedTry m = liftIOOp Control.Exception.try m++@since 0.2.1.0+-}+liftIOOp :: MonadUnliftIO m => (IO a -> IO b) -> m a -> m b+liftIOOp f x = do+ runInIO <- askRunInIO+ liftIO $ f $ runInIO x
unliftio-core.cabal view
@@ -1,35 +1,33 @@--- This file has been generated from package.yaml by hpack version 0.21.2.+cabal-version: 1.12++-- This file has been generated from package.yaml by hpack version 0.35.1. -- -- see: https://github.com/sol/hpack------ hash: 30994f07a9010e7816784501ed5ff3165c34026fa5dc555ebf1a70f6d6c0f1af name: unliftio-core-version: 0.1.1.0+version: 0.2.1.0 synopsis: The MonadUnliftIO typeclass for unlifting monads to IO description: Please see the documentation and README at <https://www.stackage.org/package/unliftio-core> category: Control homepage: https://github.com/fpco/unliftio/tree/master/unliftio-core#readme author: Michael Snoyman, Francesco Mazzoli maintainer: michael@snoyman.com-copyright: 2017 FP Complete+copyright: 2017-2020 FP Complete license: MIT license-file: LICENSE build-type: Simple-cabal-version: >= 1.10- extra-source-files:- ChangeLog.md README.md+ ChangeLog.md library- hs-source-dirs:- src- build-depends:- base >=4.5 && <4.11- , transformers >=0.2 && <0.6 exposed-modules: Control.Monad.IO.Unlift other-modules: Paths_unliftio_core+ hs-source-dirs:+ src+ build-depends:+ base >=4.9 && <4.17+ , transformers >=0.2 && <0.7 default-language: Haskell2010