|
Packit |
4b2029 |
{-# LANGUAGE CPP #-}
|
|
Packit |
4b2029 |
{-# LANGUAGE FlexibleContexts #-}
|
|
Packit |
4b2029 |
{-# LANGUAGE Trustworthy #-}
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
{-# OPTIONS_GHC -fno-warn-deprecations #-} -- Suppress warnings around Control.Monad.Trans.Error
|
|
Packit |
4b2029 |
-- | Use lazy I\/O for consuming the contents of a source. Warning: All normal
|
|
Packit |
4b2029 |
-- warnings of lazy I\/O apply. In particular, if you are using this with a
|
|
Packit |
4b2029 |
-- @ResourceT@ transformer, you must force the list to be evaluated before
|
|
Packit |
4b2029 |
-- exiting the @ResourceT@.
|
|
Packit |
4b2029 |
module Data.Conduit.Lazy
|
|
Packit |
4b2029 |
( lazyConsume
|
|
Packit |
4b2029 |
, MonadActive (..)
|
|
Packit |
4b2029 |
) where
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
import Data.Conduit
|
|
Packit |
4b2029 |
import Data.Conduit.Internal (Pipe (..), unConduitM)
|
|
Packit |
4b2029 |
import System.IO.Unsafe (unsafeInterleaveIO)
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Control (MonadBaseControl, liftBaseOp_)
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Class (lift)
|
|
Packit |
4b2029 |
import Control.Monad.IO.Class (MonadIO, liftIO)
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Identity ( IdentityT)
|
|
Packit |
4b2029 |
import Control.Monad.Trans.List ( ListT )
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Maybe ( MaybeT )
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Error ( ErrorT, Error)
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Reader ( ReaderT )
|
|
Packit |
4b2029 |
import Control.Monad.Trans.State ( StateT )
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Writer ( WriterT )
|
|
Packit |
4b2029 |
import Control.Monad.Trans.RWS ( RWST )
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
import qualified Control.Monad.Trans.RWS.Strict as Strict ( RWST )
|
|
Packit |
4b2029 |
import qualified Control.Monad.Trans.State.Strict as Strict ( StateT )
|
|
Packit |
4b2029 |
import qualified Control.Monad.Trans.Writer.Strict as Strict ( WriterT )
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
#if (__GLASGOW_HASKELL__ < 710)
|
|
Packit |
4b2029 |
import Data.Monoid (Monoid)
|
|
Packit |
4b2029 |
#endif
|
|
Packit |
4b2029 |
import Control.Monad.ST (ST)
|
|
Packit |
4b2029 |
import qualified Control.Monad.ST.Lazy as Lazy
|
|
Packit |
4b2029 |
import Data.Functor.Identity (Identity)
|
|
Packit |
4b2029 |
import Control.Monad.Trans.Resource.Internal (ResourceT (ResourceT), ReleaseMap (ReleaseMapClosed))
|
|
Packit |
4b2029 |
import qualified Data.IORef as I
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
-- | Use lazy I\/O to consume all elements from a @Source@.
|
|
Packit |
4b2029 |
--
|
|
Packit |
4b2029 |
-- This function relies on 'monadActive' to determine if the underlying monadic
|
|
Packit |
4b2029 |
-- state has been closed.
|
|
Packit |
4b2029 |
--
|
|
Packit |
4b2029 |
-- Since 0.3.0
|
|
Packit |
4b2029 |
lazyConsume :: (MonadBaseControl IO m, MonadActive m) => Source m a -> m [a]
|
|
Packit |
4b2029 |
lazyConsume =
|
|
Packit |
4b2029 |
#if MIN_VERSION_conduit(1, 2, 0)
|
|
Packit |
4b2029 |
go . flip unConduitM Done
|
|
Packit |
4b2029 |
#else
|
|
Packit |
4b2029 |
go . unConduitM
|
|
Packit |
4b2029 |
#endif
|
|
Packit |
4b2029 |
where
|
|
Packit |
4b2029 |
go (Done _) = return []
|
|
Packit |
4b2029 |
go (HaveOutput src _ x) = do
|
|
Packit |
4b2029 |
xs <- liftBaseOp_ unsafeInterleaveIO $ go src
|
|
Packit |
4b2029 |
return $ x : xs
|
|
Packit |
4b2029 |
go (PipeM msrc) = liftBaseOp_ unsafeInterleaveIO $ do
|
|
Packit |
4b2029 |
a <- monadActive
|
|
Packit |
4b2029 |
if a
|
|
Packit |
4b2029 |
then msrc >>= go
|
|
Packit |
4b2029 |
else return []
|
|
Packit |
4b2029 |
go (NeedInput _ c) = go (c ())
|
|
Packit |
4b2029 |
go (Leftover p _) = go p
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
-- | Determine if some monad is still active. This is intended to prevent usage
|
|
Packit |
4b2029 |
-- of a monadic state after it has been closed. This is necessary for such
|
|
Packit |
4b2029 |
-- cases as lazy I\/O, where an unevaluated thunk may still refer to a
|
|
Packit |
4b2029 |
-- closed @ResourceT@.
|
|
Packit |
4b2029 |
--
|
|
Packit |
4b2029 |
-- Since 0.3.0
|
|
Packit |
4b2029 |
class Monad m => MonadActive m where
|
|
Packit |
4b2029 |
monadActive :: m Bool
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
instance (MonadIO m, MonadActive m) => MonadActive (ResourceT m) where
|
|
Packit |
4b2029 |
monadActive = ResourceT $ \rmMap -> do
|
|
Packit |
4b2029 |
rm <- liftIO $ I.readIORef rmMap
|
|
Packit |
4b2029 |
case rm of
|
|
Packit |
4b2029 |
ReleaseMapClosed -> return False
|
|
Packit |
4b2029 |
_ -> monadActive -- recurse
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
instance MonadActive Identity where
|
|
Packit |
4b2029 |
monadActive = return True
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
instance MonadActive IO where
|
|
Packit |
4b2029 |
monadActive = return True
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
instance MonadActive (ST s) where
|
|
Packit |
4b2029 |
monadActive = return True
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
instance MonadActive (Lazy.ST s) where
|
|
Packit |
4b2029 |
monadActive = return True
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
#define GO(T) instance MonadActive m => MonadActive (T m) where monadActive = lift monadActive
|
|
Packit |
4b2029 |
#define GOX(X, T) instance (X, MonadActive m) => MonadActive (T m) where monadActive = lift monadActive
|
|
Packit |
4b2029 |
GO(IdentityT)
|
|
Packit |
4b2029 |
GO(ListT)
|
|
Packit |
4b2029 |
GO(MaybeT)
|
|
Packit |
4b2029 |
GOX(Error e, ErrorT e)
|
|
Packit |
4b2029 |
GO(ReaderT r)
|
|
Packit |
4b2029 |
GO(StateT s)
|
|
Packit |
4b2029 |
GOX(Monoid w, WriterT w)
|
|
Packit |
4b2029 |
GOX(Monoid w, RWST r w s)
|
|
Packit |
4b2029 |
GOX(Monoid w, Strict.RWST r w s)
|
|
Packit |
4b2029 |
GO(Strict.StateT s)
|
|
Packit |
4b2029 |
GOX(Monoid w, Strict.WriterT w)
|
|
Packit |
4b2029 |
#undef GO
|
|
Packit |
4b2029 |
#undef GOX
|
|
Packit |
4b2029 |
|
|
Packit |
4b2029 |
instance MonadActive m => MonadActive (Pipe l i o u m) where
|
|
Packit |
4b2029 |
monadActive = lift monadActive
|
|
Packit |
4b2029 |
instance MonadActive m => MonadActive (ConduitM i o m) where
|
|
Packit |
4b2029 |
monadActive = lift monadActive
|