{-# LANGUAGE RankNTypes #-}
module Control.Monad.IO.Unlift
( MonadUnliftIO (..)
, UnliftIO (..)
, askUnliftIO
, askRunInIO
, withUnliftIO
, toIO
, wrappedWithRunInIO
, liftIOOp
, MonadIO (..)
) where
import Control.Monad.IO.Class
import Control.Monad.Trans.Reader (ReaderT (..))
import Control.Monad.Trans.Identity (IdentityT (..))
newtype UnliftIO m = UnliftIO { UnliftIO m -> forall a. m a -> IO a
unliftIO :: forall a. m a -> IO a }
class MonadIO m => MonadUnliftIO m where
withRunInIO :: ((forall a. m a -> IO a) -> IO b) -> m b
instance MonadUnliftIO IO where
{-# INLINE withRunInIO #-}
withRunInIO :: ((forall a. IO a -> IO a) -> IO b) -> IO b
withRunInIO (forall a. IO a -> IO a) -> IO b
inner = (forall a. IO a -> IO a) -> IO b
inner forall a. a -> a
forall a. IO a -> IO a
id
instance MonadUnliftIO m => MonadUnliftIO (ReaderT r m) where
{-# INLINE withRunInIO #-}
withRunInIO :: ((forall a. ReaderT r m a -> IO a) -> IO b) -> ReaderT r m b
withRunInIO (forall a. ReaderT r m a -> IO a) -> IO b
inner =
(r -> m b) -> ReaderT r m b
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((r -> m b) -> ReaderT r m b) -> (r -> m b) -> ReaderT r m b
forall a b. (a -> b) -> a -> b
$ \r
r ->
((forall a. m a -> IO a) -> IO b) -> m b
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO b) -> m b)
-> ((forall a. m a -> IO a) -> IO b) -> m b
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
run ->
(forall a. ReaderT r m a -> IO a) -> IO b
inner (m a -> IO a
forall a. m a -> IO a
run (m a -> IO a) -> (ReaderT r m a -> m a) -> ReaderT r m a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ReaderT r m a -> r -> m a) -> r -> ReaderT r m a -> m a
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT r m a -> r -> m a
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT r
r)
instance MonadUnliftIO m => MonadUnliftIO (IdentityT m) where
{-# INLINE withRunInIO #-}
withRunInIO :: ((forall a. IdentityT m a -> IO a) -> IO b) -> IdentityT m b
withRunInIO (forall a. IdentityT m a -> IO a) -> IO b
inner =
m b -> IdentityT m b
forall k (f :: k -> *) (a :: k). f a -> IdentityT f a
IdentityT (m b -> IdentityT m b) -> m b -> IdentityT m b
forall a b. (a -> b) -> a -> b
$
((forall a. m a -> IO a) -> IO b) -> m b
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO b) -> m b)
-> ((forall a. m a -> IO a) -> IO b) -> m b
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
run ->
(forall a. IdentityT m a -> IO a) -> IO b
inner (m a -> IO a
forall a. m a -> IO a
run (m a -> IO a) -> (IdentityT m a -> m a) -> IdentityT m a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IdentityT m a -> m a
forall k (f :: k -> *) (a :: k). IdentityT f a -> f a
runIdentityT)
askUnliftIO :: MonadUnliftIO m => m (UnliftIO m)
askUnliftIO :: m (UnliftIO m)
askUnliftIO = ((forall a. m a -> IO a) -> IO (UnliftIO m)) -> m (UnliftIO m)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (\forall a. m a -> IO a
run -> UnliftIO m -> IO (UnliftIO m)
forall (m :: * -> *) a. Monad m => a -> m a
return ((forall a. m a -> IO a) -> UnliftIO m
forall (m :: * -> *). (forall a. m a -> IO a) -> UnliftIO m
UnliftIO forall a. m a -> IO a
run))
{-# INLINE askUnliftIO #-}
{-# INLINE askRunInIO #-}
askRunInIO :: MonadUnliftIO m => m (m a -> IO a)
askRunInIO :: m (m a -> IO a)
askRunInIO = ((forall a. m a -> IO a) -> IO (m a -> IO a)) -> m (m a -> IO a)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (\forall a. m a -> IO a
run -> ((m a -> IO a) -> IO (m a -> IO a)
forall (m :: * -> *) a. Monad m => a -> m a
return (\m a
ma -> m a -> IO a
forall a. m a -> IO a
run m a
ma)))
{-# INLINE withUnliftIO #-}
withUnliftIO :: MonadUnliftIO m => (UnliftIO m -> IO a) -> m a
withUnliftIO :: (UnliftIO m -> IO a) -> m a
withUnliftIO UnliftIO m -> IO a
inner = m (UnliftIO m)
forall (m :: * -> *). MonadUnliftIO m => m (UnliftIO m)
askUnliftIO m (UnliftIO m) -> (UnliftIO m -> m a) -> m a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO a -> m a) -> (UnliftIO m -> IO a) -> UnliftIO m -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UnliftIO m -> IO a
inner
{-# INLINE toIO #-}
toIO :: MonadUnliftIO m => m a -> m (IO a)
toIO :: m a -> m (IO a)
toIO m a
m = ((forall a. m a -> IO a) -> IO (IO a)) -> m (IO a)
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. m a -> IO a) -> IO (IO a)) -> m (IO a))
-> ((forall a. m a -> IO a) -> IO (IO a)) -> m (IO a)
forall a b. (a -> b) -> a -> b
$ \forall a. m a -> IO a
run -> IO a -> IO (IO a)
forall (m :: * -> *) a. Monad m => a -> m a
return (IO a -> IO (IO a)) -> IO a -> IO (IO a)
forall a b. (a -> b) -> a -> b
$ m a -> IO a
forall a. m a -> IO a
run m a
m
{-# INLINE wrappedWithRunInIO #-}
wrappedWithRunInIO :: MonadUnliftIO n
=> (n b -> m b)
-> (forall a. m a -> n a)
-> ((forall a. m a -> IO a) -> IO b)
-> m b
wrappedWithRunInIO :: (n b -> m b)
-> (forall a. m a -> n a)
-> ((forall a. m a -> IO a) -> IO b)
-> m b
wrappedWithRunInIO n b -> m b
wrap forall a. m a -> n a
unwrap (forall a. m a -> IO a) -> IO b
inner = n b -> m b
wrap (n b -> m b) -> n b -> m b
forall a b. (a -> b) -> a -> b
$ ((forall a. n a -> IO a) -> IO b) -> n b
forall (m :: * -> *) b.
MonadUnliftIO m =>
((forall a. m a -> IO a) -> IO b) -> m b
withRunInIO (((forall a. n a -> IO a) -> IO b) -> n b)
-> ((forall a. n a -> IO a) -> IO b) -> n b
forall a b. (a -> b) -> a -> b
$ \forall a. n a -> IO a
run ->
(forall a. m a -> IO a) -> IO b
inner ((forall a. m a -> IO a) -> IO b)
-> (forall a. m a -> IO a) -> IO b
forall a b. (a -> b) -> a -> b
$ n a -> IO a
forall a. n a -> IO a
run (n a -> IO a) -> (m a -> n a) -> m a -> IO a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> n a
forall a. m a -> n a
unwrap
liftIOOp :: MonadUnliftIO m => (IO a -> IO b) -> m a -> m b
liftIOOp :: (IO a -> IO b) -> m a -> m b
liftIOOp IO a -> IO b
f m a
x = do
m a -> IO a
runInIO <- m (m a -> IO a)
forall (m :: * -> *) a. MonadUnliftIO m => m (m a -> IO a)
askRunInIO
IO b -> m b
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO b -> m b) -> IO b -> m b
forall a b. (a -> b) -> a -> b
$ IO a -> IO b
f (IO a -> IO b) -> IO a -> IO b
forall a b. (a -> b) -> a -> b
$ m a -> IO a
runInIO m a
x