{-# LANGUAGE CPP #-}
module Pipes.Lift (
distribute
, exceptP
, runExceptP
, catchError
, liftCatchError
, maybeP
, runMaybeP
, readerP
, runReaderP
, stateP
, runStateP
, evalStateP
, execStateP
, writerP
, runWriterP
, execWriterP
, rwsP
, runRWSP
, evalRWSP
, execRWSP
) where
import Control.Monad.Trans.Class (lift, MonadTrans(..))
import qualified Control.Monad.Trans.Except as E
import qualified Control.Monad.Trans.Maybe as M
import qualified Control.Monad.Trans.Reader as R
import qualified Control.Monad.Trans.State.Strict as S
import qualified Control.Monad.Trans.Writer.Strict as W
import qualified Control.Monad.Trans.RWS.Strict as RWS
import Pipes.Internal (Proxy(..), unsafeHoist)
import Control.Monad.Morph (hoist, MFunctor(..))
import Pipes.Core (runEffect, request, respond, (//>), (>\\))
#if MIN_VERSION_base(4,8,0)
#else
import Data.Monoid
#endif
distribute
:: ( Monad m
, MonadTrans t
, MFunctor t
, Monad (t m)
, Monad (t (Proxy a' a b' b m))
)
=> Proxy a' a b' b (t m) r
-> t (Proxy a' a b' b m) r
distribute p = runEffect $ request' >\\ unsafeHoist (hoist lift) p //> respond'
where
request' = lift . lift . request
respond' = lift . lift . respond
{-# INLINABLE distribute #-}
exceptP
:: Monad m
=> Proxy a' a b' b m (Either e r)
-> Proxy a' a b' b (E.ExceptT e m) r
exceptP p = do
x <- unsafeHoist lift p
lift $ E.ExceptT (return x)
{-# INLINABLE exceptP #-}
runExceptP
:: Monad m
=> Proxy a' a b' b (E.ExceptT e m) r
-> Proxy a' a b' b m (Either e r)
runExceptP = E.runExceptT . distribute
{-# INLINABLE runExceptP #-}
catchError
:: Monad m
=> Proxy a' a b' b (E.ExceptT e m) r
-> (e -> Proxy a' a b' b (E.ExceptT e m) r)
-> Proxy a' a b' b (E.ExceptT e m) r
catchError e h = exceptP . E.runExceptT $
E.catchE (distribute e) (distribute . h)
{-# INLINABLE catchError #-}
liftCatchError
:: Monad m
=> ( m (Proxy a' a b' b m r)
-> (e -> m (Proxy a' a b' b m r))
-> m (Proxy a' a b' b m r) )
-> (Proxy a' a b' b m r
-> (e -> Proxy a' a b' b m r)
-> Proxy a' a b' b m r)
liftCatchError c p0 f = go p0
where
go p = case p of
Request a' fa -> Request a' (\a -> go (fa a ))
Respond b fb' -> Respond b (\b' -> go (fb' b'))
Pure r -> Pure r
M m -> M ((do
p' <- m
return (go p') ) `c` (\e -> return (f e)) )
{-# INLINABLE liftCatchError #-}
maybeP
:: Monad m
=> Proxy a' a b' b m (Maybe r) -> Proxy a' a b' b (M.MaybeT m) r
maybeP p = do
x <- unsafeHoist lift p
lift $ M.MaybeT (return x)
{-# INLINABLE maybeP #-}
runMaybeP
:: Monad m
=> Proxy a' a b' b (M.MaybeT m) r
-> Proxy a' a b' b m (Maybe r)
runMaybeP p = M.runMaybeT $ distribute p
{-# INLINABLE runMaybeP #-}
readerP
:: Monad m
=> (i -> Proxy a' a b' b m r) -> Proxy a' a b' b (R.ReaderT i m) r
readerP k = do
i <- lift R.ask
unsafeHoist lift (k i)
{-# INLINABLE readerP #-}
runReaderP
:: Monad m
=> i
-> Proxy a' a b' b (R.ReaderT i m) r
-> Proxy a' a b' b m r
runReaderP r p = (`R.runReaderT` r) $ distribute p
{-# INLINABLE runReaderP #-}
stateP
:: Monad m
=> (s -> Proxy a' a b' b m (r, s)) -> Proxy a' a b' b (S.StateT s m) r
stateP k = do
s <- lift S.get
(r, s') <- unsafeHoist lift (k s)
lift (S.put s')
return r
{-# INLINABLE stateP #-}
runStateP
:: Monad m
=> s
-> Proxy a' a b' b (S.StateT s m) r
-> Proxy a' a b' b m (r, s)
runStateP s p = (`S.runStateT` s) $ distribute p
{-# INLINABLE runStateP #-}
evalStateP
:: Monad m
=> s
-> Proxy a' a b' b (S.StateT s m) r
-> Proxy a' a b' b m r
evalStateP s p = fmap fst $ runStateP s p
{-# INLINABLE evalStateP #-}
execStateP
:: Monad m
=> s
-> Proxy a' a b' b (S.StateT s m) r
-> Proxy a' a b' b m s
execStateP s p = fmap snd $ runStateP s p
{-# INLINABLE execStateP #-}
writerP
:: (Monad m, Monoid w)
=> Proxy a' a b' b m (r, w) -> Proxy a' a b' b (W.WriterT w m) r
writerP p = do
(r, w) <- unsafeHoist lift p
lift $ W.tell w
return r
{-# INLINABLE writerP #-}
runWriterP
:: (Monad m, Monoid w)
=> Proxy a' a b' b (W.WriterT w m) r
-> Proxy a' a b' b m (r, w)
runWriterP p = W.runWriterT $ distribute p
{-# INLINABLE runWriterP #-}
execWriterP
:: (Monad m, Monoid w)
=> Proxy a' a b' b (W.WriterT w m) r
-> Proxy a' a b' b m w
execWriterP p = fmap snd $ runWriterP p
{-# INLINABLE execWriterP #-}
rwsP
:: (Monad m, Monoid w)
=> (i -> s -> Proxy a' a b' b m (r, s, w))
-> Proxy a' a b' b (RWS.RWST i w s m) r
rwsP k = do
i <- lift RWS.ask
s <- lift RWS.get
(r, s', w) <- unsafeHoist lift (k i s)
lift $ do
RWS.put s'
RWS.tell w
return r
{-# INLINABLE rwsP #-}
runRWSP
:: (Monad m, Monoid w)
=> r
-> s
-> Proxy a' a b' b (RWS.RWST r w s m) d
-> Proxy a' a b' b m (d, s, w)
runRWSP i s p = (\b -> RWS.runRWST b i s) $ distribute p
{-# INLINABLE runRWSP #-}
evalRWSP
:: (Monad m, Monoid w)
=> r
-> s
-> Proxy a' a b' b (RWS.RWST r w s m) d
-> Proxy a' a b' b m (d, w)
evalRWSP i s p = fmap f $ runRWSP i s p
where
f x = let (r, _, w) = x in (r, w)
{-# INLINABLE evalRWSP #-}
execRWSP
:: (Monad m, Monoid w)
=> r
-> s
-> Proxy a' a b' b (RWS.RWST r w s m) d
-> Proxy a' a b' b m (s, w)
execRWSP i s p = fmap f $ runRWSP i s p
where
f x = let (_, s', w) = x in (s', w)
{-# INLINABLE execRWSP #-}