conduit-combinators (empty) → 0.1.0.0
raw patch · 7 files changed
+3218/−0 lines, 7 filesdep +basedep +basic-preludedep +bytestringsetup-changed
Dependencies added: base, basic-prelude, bytestring, chunked-data, conduit, conduit-combinators, hspec, mono-traversable, primitive, silently, system-fileio, system-filepath, text, transformers, transformers-base, vector
Files
- Conduit.hs +38/−0
- Data/Conduit/Combinators.hs +1433/−0
- Data/Conduit/Combinators/Unqualified.hs +1172/−0
- LICENSE +20/−0
- Setup.hs +2/−0
- conduit-combinators.cabal +51/−0
- test/Spec.hs +502/−0
+ Conduit.hs view
@@ -0,0 +1,38 @@+{-# LANGUAGE CPP #-}+-- | Your intended one-stop-shop for conduit functionality.+-- This re-exports functions from many commonly used modules.+-- When there is a conflict with standard functions, functions+-- in this module are disambiguated by adding a trailing C+-- (or for chunked functions, replacing a trailing E with EC).+-- This means that the Conduit module can be imported unqualified+-- without causing naming conflicts.+--+-- For more information on the naming scheme and intended usages of the+-- combinators, please see the "Data.Conduit.Combinators" documentation.+module Conduit+ ( -- * Core conduit library+ module Data.Conduit+ , module Data.Conduit.Util+#if MIN_VERSION_conduit(1, 0, 11)+ , module Data.Conduit.Lift+#endif+ -- * Commonly used combinators+ , module Data.Conduit.Combinators.Unqualified+ -- * Monadic lifting+ , MonadIO (..)+ , MonadTrans (..)+ , MonadBase (..)+ -- * Pure pipelines+ , Identity (..)+ ) where++import Data.Conduit+import Data.Conduit.Util hiding (zip)+import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad.Trans.Class (MonadTrans (..))+import Control.Monad.Base (MonadBase (..))+#if MIN_VERSION_conduit(1, 0, 11)+import Data.Conduit.Lift+#endif+import Data.Conduit.Combinators.Unqualified+import Data.Functor.Identity (Identity (..))
+ Data/Conduit/Combinators.hs view
@@ -0,0 +1,1433 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+-- | This module is meant as a replacement for Data.Conduit.List.+-- That module follows a naming scheme which was originally inspired+-- by its enumerator roots. This module is meant to introduce a naming+-- scheme which encourages conduit best practices.+--+-- There are two versions of functions in this module. Those with a trailing+-- E work in the individual elements of a chunk of data, e.g., the bytes of+-- a ByteString, the Chars of a Text, or the Ints of a Vector Int. Those+-- without a trailing E work on unchunked streams.+--+-- FIXME: discuss overall naming, usage of mono-traversable, etc+--+-- Mention take (Conduit) vs drop (Consumer)+module Data.Conduit.Combinators+ ( -- * Producers+ -- ** Pure+ yieldMany+ , unfold+ , enumFromTo+ , iterate+ , repeat+ , replicate+ , sourceLazy++ -- ** Monadic+ , repeatM+ , repeatWhileM+ , replicateM++ -- ** I\/O+ , sourceFile+ , sourceHandle+ , sourceIOHandle+ , stdin++ -- * Consumers+ -- ** Pure+ , drop+ , dropE+ , dropWhile+ , dropWhileE+ , fold+ , foldE+ , foldl+ , foldlE+ , foldMap+ , foldMapE+ , all+ , allE+ , any+ , anyE+ , and+ , andE+ , or+ , orE+ , elem+ , elemE+ , notElem+ , notElemE+ , sinkLazy+ , sinkList+ , sinkVector+ , sinkBuilder+ , sinkLazyBuilder+ , sinkNull+ , awaitNonNull+ , headE+ , peek+ , peekE+ , last+ , lastE+ , length+ , lengthE+ , maximum+ , maximumE+ , minimum+ , minimumE+ , null+ , nullE+ , sum+ , sumE+ , product+ , productE+ , find++ -- ** Monadic+ , mapM_+ , mapM_E+ , foldM+ , foldME+ , foldMapM+ , foldMapME++ -- ** I\/O+ , sinkFile+ , sinkHandle+ , sinkIOHandle+ , print+ , stdout+ , stderr++ -- * Transformers+ -- ** Pure+ , map+ , mapE+ , omapE+ , concatMap+ , concatMapE+ , take+ , takeE+ , takeWhile+ , takeWhileE+ , takeExactly+ , takeExactlyE+ , concat+ , filter+ , filterE+ , mapWhile+ , conduitVector+ , scanl+ , concatMapAccum+ , intersperse++ -- ** Monadic+ , mapM+ , mapME+ , omapME+ , concatMapM+ , filterM+ , filterME+ , iterM+ , scanlM+ , concatMapAccumM++ -- ** Textual+ , encodeUtf8+ , decodeUtf8+ , line+ , lineAscii+ , unlines+ , unlinesAscii+ , linesUnbounded+ , linesUnboundedAscii+ ) where++-- BEGIN IMPORTS++import Data.Builder+import qualified Data.NonNull as NonNull+import qualified Data.Traversable+import Control.Applicative ((<$>))+import Control.Category (Category (..))+import Control.Monad (unless, when, (>=>), liftM, forever)+import Control.Monad.Base (MonadBase (liftBase))+import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad.Primitive (PrimMonad)+import Control.Monad.Trans.Class (lift)+import Data.Conduit+import qualified Data.Conduit.List as CL+import Data.IOData+import Data.Monoid (Monoid (..))+import Data.MonoTraversable+import qualified Data.Sequences as Seq+import Data.Sequences.Lazy+import qualified Data.Vector.Generic as V+import qualified Data.Vector.Generic.Mutable as VM+import qualified Filesystem as F+import Filesystem.Path (FilePath)+import Prelude (Bool (..), Eq (..), Int,+ Maybe (..), Monad (..), Num (..),+ Ord (..), fromIntegral, maybe,+ ($), Functor (..), Enum, seq, Show, Char)+import Data.Word (Word8)+import qualified Prelude+import System.IO (Handle)+import qualified System.IO as SIO+import qualified Data.Textual.Encoding as DTE+import qualified Data.Conduit.Text as CT+import Data.ByteString (ByteString)+import Data.Text (Text)++-- END IMPORTS++-- | Yield each of the values contained by the given @MonoFoldable@.+--+-- This will work on many data structures, including lists, @ByteString@s, and @Vector@s.+--+-- Since 1.0.0+yieldMany :: (Monad m, MonoFoldable mono)+ => mono+ -> Producer m (Element mono)+yieldMany = ofoldMap yield+{-# INLINE yieldMany #-}++-- | Generate a producer from a seed value.+--+-- Since 1.0.0+unfold :: Monad m+ => (b -> Maybe (a, b))+ -> b+ -> Producer m a+unfold = CL.unfold+{-# INLINE unfold #-}++-- | Enumerate from a value to a final value, inclusive, via 'succ'.+--+-- This is generally more efficient than using @Prelude@\'s @enumFromTo@ and+-- combining with @sourceList@ since this avoids any intermediate data+-- structures.+--+-- Since 1.0.0+enumFromTo :: (Monad m, Enum a, Eq a) => a -> a -> Producer m a+enumFromTo = CL.enumFromTo++-- | Produces an infinite stream of repeated applications of f to x.+--+-- Since 1.0.0+iterate :: Monad m => (a -> a) -> a -> Producer m a+iterate = CL.iterate+{-# INLINE iterate #-}++-- | Produce an infinite stream consisting entirely of the given value.+--+-- Since 1.0.0+repeat :: Monad m => a -> Producer m a+repeat = iterate id+{-# INLINE repeat #-}++-- | Produce a finite stream consisting of n copies of the given value.+--+-- Since 1.0.0+replicate :: Monad m+ => Int+ -> a+ -> Producer m a+replicate count0 a =+ loop count0+ where+ loop count = if count <= 0+ then return ()+ else yield a >> loop (count - 1)+{-# INLINE replicate #-}++-- | Generate a producer by yielding each of the strict chunks in a @LazySequence@.+--+-- For more information, see 'toChunks'.+--+-- Since 1.0.0+sourceLazy :: (Monad m, LazySequence lazy strict)+ => lazy+ -> Producer m strict+sourceLazy = yieldMany . toChunks+{-# INLINE sourceLazy #-}++-- | Repeatedly run the given action and yield all values it produces.+--+-- Since 1.0.0+repeatM :: Monad m+ => m a+ -> Producer m a+repeatM m = forever $ lift m >>= yield+{-# INLINE repeatM #-}++-- | Repeatedly run the given action and yield all values it produces, until+-- the provided predicate returns @False@.+--+-- Since 1.0.0+repeatWhileM :: Monad m+ => m a+ -> (a -> Bool)+ -> Producer m a+repeatWhileM m f =+ loop+ where+ loop = do+ x <- lift m+ when (f x) $ yield x >> loop++-- | Perform the given action n times, yielding each result.+--+-- Since 1.0.0+replicateM :: Monad m+ => Int+ -> m a+ -> Producer m a+replicateM count0 m =+ loop count0+ where+ loop count = if count <= 0+ then return ()+ else lift m >>= yield >> loop (count - 1)+{-# INLINE replicateM #-}++-- | Read all data from the given file.+--+-- This function automatically opens and closes the file handle, and ensures+-- exception safety via @MonadResource. It works for all instances of @IOData@,+-- including @ByteString@ and @Text@.+--+-- Since 1.0.0+sourceFile :: (MonadResource m, IOData a) => FilePath -> Producer m a+sourceFile fp = sourceIOHandle (F.openFile fp SIO.ReadMode)+{-# INLINE sourceFile #-}++-- | Read all data from the given @Handle@.+--+-- Does not close the @Handle@ at any point.+--+-- Since 1.0.0+sourceHandle :: (MonadIO m, IOData a) => Handle -> Producer m a+sourceHandle h =+ loop+ where+ loop = do+ x <- liftIO (hGetChunk h)+ if onull x+ then return ()+ else yield x >> loop+{-# INLINEABLE sourceHandle #-}++-- | Open a @Handle@ using the given function and stream data from it.+--+-- Automatically closes the file at completion.+--+-- Since 1.0.0+sourceIOHandle :: (MonadResource m, IOData a) => SIO.IO Handle -> Producer m a+sourceIOHandle alloc = bracketP alloc SIO.hClose sourceHandle+{-# INLINE sourceIOHandle #-}++-- | @sourceHandle@ applied to @stdin@.+--+-- Since 1.0.0+stdin :: (MonadIO m, IOData a) => Producer m a+stdin = sourceHandle SIO.stdin++-- | Ignore a certain number of values in the stream.+--+-- Since 1.0.0+drop :: Monad m+ => Int+ -> Consumer a m ()+drop =+ loop+ where+ loop i | i <= 0 = return ()+ loop count = await >>= maybe (return ()) (\_ -> loop (count - 1))+{-# INLINE drop #-}++-- | Drop a certain number of elements from a chunked stream.+--+-- Since 1.0.0+dropE :: (Monad m, Seq.IsSequence seq)+ => Seq.Index seq+ -> Consumer seq m ()+dropE =+ loop+ where+ loop i = if i <= 0+ then return ()+ else await >>= maybe (return ()) (go i)++ go i seq = do+ unless (onull y) $ leftover y+ loop i'+ where+ (x, y) = Seq.splitAt i seq+ i' = i - fromIntegral (olength x)+{-# INLINEABLE dropE #-}++-- | Drop all values which match the given predicate.+--+-- Since 1.0.0+dropWhile :: Monad m+ => (a -> Bool)+ -> Consumer a m ()+dropWhile f =+ loop+ where+ loop = await >>= maybe (return ()) go+ go x = if f x then loop else leftover x+{-# INLINE dropWhile #-}++-- | Drop all elements in the chunked stream which match the given predicate.+--+-- Since 1.0.0+dropWhileE :: (Monad m, Seq.IsSequence seq)+ => (Element seq -> Bool)+ -> Consumer seq m ()+dropWhileE f =+ loop+ where+ loop = await >>= maybe (return ()) go++ go seq =+ if onull x then loop else leftover x+ where+ x = Seq.dropWhile f seq+{-# INLINE dropWhileE #-}++-- | Monoidally combine all values in the stream.+--+-- Since 1.0.0+fold :: (Monad m, Monoid a)+ => Consumer a m a+fold = CL.foldMap id+{-# INLINE fold #-}++-- | Monoidally combine all elements in the chunked stream.+--+-- Since 1.0.0+foldE :: (Monad m, MonoFoldable mono, Monoid (Element mono))+ => Consumer mono m (Element mono)+foldE = CL.fold (\accum mono -> accum `mappend` ofoldMap id mono) mempty+{-# INLINE foldE #-}++-- | A strict left fold.+--+-- Since 1.0.0+foldl :: Monad m => (a -> b -> a) -> a -> Consumer b m a+foldl = CL.fold+{-# INLINE foldl #-}++-- | A strict left fold on a chunked stream.+--+-- Since 1.0.0+foldlE :: (Monad m, MonoFoldable mono)+ => (a -> Element mono -> a)+ -> a+ -> Consumer mono m a+foldlE f = CL.fold (ofoldl' f)+{-# INLINE foldlE #-}++-- | Apply the provided mapping function and monoidal combine all values.+--+-- Since 1.0.0+foldMap :: (Monad m, Monoid b)+ => (a -> b)+ -> Consumer a m b+foldMap = CL.foldMap+{-# INLINE foldMap #-}++-- | Apply the provided mapping function and monoidal combine all elements of the chunked stream.+--+-- Since 1.0.0+foldMapE :: (Monad m, MonoFoldable mono, Monoid w)+ => (Element mono -> w)+ -> Consumer mono m w+foldMapE = CL.foldMap . ofoldMap+{-# INLINE foldMapE #-}++-- | Check that all values in the stream return True.+--+-- Subject to shortcut logic: at the first False, consumption of the stream+-- will stop.+--+-- Since 1.0.0+all :: Monad m+ => (a -> Bool)+ -> Consumer a m Bool+all f =+ loop+ where+ loop = await >>= maybe (return True) go+ go x = if f x then loop else return False+{-# INLINE all #-}++-- | Check that all elements in the chunked stream return True.+--+-- Subject to shortcut logic: at the first False, consumption of the stream+-- will stop.+--+-- Since 1.0.0+allE :: (Monad m, MonoFoldable mono)+ => (Element mono -> Bool)+ -> Consumer mono m Bool+allE = all . oall++-- | Check that at least one value in the stream returns True.+--+-- Subject to shortcut logic: at the first True, consumption of the stream+-- will stop.+--+-- Since 1.0.0+any :: Monad m+ => (a -> Bool)+ -> Consumer a m Bool+any f =+ loop+ where+ loop = await >>= maybe (return False) go+ go x = if f x then return True else loop+{-# INLINE any #-}++-- | Check that at least one element in the chunked stream returns True.+--+-- Subject to shortcut logic: at the first True, consumption of the stream+-- will stop.+--+-- Since 1.0.0+anyE :: (Monad m, MonoFoldable mono)+ => (Element mono -> Bool)+ -> Consumer mono m Bool+anyE = any . oany++-- | Are all values in the stream True?+--+-- Consumption stops once the first False is encountered.+--+-- Since 1.0.0+and :: Monad m => Consumer Bool m Bool+and = all id+{-# INLINE and #-}++-- | Are all elements in the chunked stream True?+--+-- Consumption stops once the first False is encountered.+--+-- Since 1.0.0+andE :: (Monad m, MonoFoldable mono, Element mono ~ Bool)+ => Consumer mono m Bool+andE = allE id+{-# INLINE andE #-}++-- | Are any values in the stream True?+--+-- Consumption stops once the first True is encountered.+--+-- Since 1.0.0+or :: Monad m => Consumer Bool m Bool+or = any id+{-# INLINE or #-}++-- | Are any elements in the chunked stream True?+--+-- Consumption stops once the first True is encountered.+--+-- Since 1.0.0+orE :: (Monad m, MonoFoldable mono, Element mono ~ Bool)+ => Consumer mono m Bool+orE = anyE id+{-# INLINE orE #-}++-- | Are any values in the stream equal to the given value?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+elem :: (Monad m, Eq a) => a -> Consumer a m Bool+elem x = any (== x)+{-# INLINE elem #-}++-- | Are any elements in the chunked stream equal to the given element?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+elemE :: (Monad m, Seq.EqSequence seq)+ => Element seq+ -> Consumer seq m Bool+elemE = any . Seq.elem++-- | Are no values in the stream equal to the given value?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+notElem :: (Monad m, Eq a) => a -> Consumer a m Bool+notElem x = all (/= x)+{-# INLINE notElem #-}++-- | Are no elements in the chunked stream equal to the given element?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+notElemE :: (Monad m, Seq.EqSequence seq)+ => Element seq+ -> Consumer seq m Bool+notElemE = all . Seq.notElem++-- | Consume all incoming strict chunks into a lazy sequence.+-- Note that the entirety of the sequence will be resident at memory.+--+-- This can be used to consume a stream of strict ByteStrings into a lazy+-- ByteString, for example.+--+-- Since 1.0.0+sinkLazy :: (Monad m, LazySequence lazy strict)+ => Consumer strict m lazy+sinkLazy = (fromChunks . ($ [])) <$> CL.fold (\front next -> front . (next:)) id+{-# INLINE sinkLazy #-}++-- | Consume all values from the stream and return as a list. Note that this+-- will pull all values into memory.+--+-- Since 1.0.0+sinkList :: Monad m => Consumer a m [a]+sinkList = CL.consume+{-# INLINE sinkList #-}++-- | Sink incoming values into a vector, up until size @maxSize@. Subsequent+-- values will be left in the stream. If there are less than @maxSize@ values+-- present, returns a @Vector@ of smaller size.+--+-- Note that using this function is more memory efficient than @sinkList@ and+-- then converting to a @Vector@, as it avoids intermediate list constructors.+--+-- Since 1.0.0+sinkVector :: (MonadBase base m, V.Vector v a, PrimMonad base)+ => Int -- ^ maximum allowed size+ -> Consumer a m (v a)+sinkVector maxSize = do+ mv <- liftBase $ VM.new maxSize+ let go i | i >= maxSize = liftBase $ V.unsafeFreeze mv+ go i = do+ mx <- await+ case mx of+ Nothing -> V.slice 0 i <$> liftBase (V.unsafeFreeze mv)+ Just x -> do+ liftBase $ VM.write mv i x+ go (i + 1)+ go 0+{-# INLINEABLE sinkVector #-}++-- | Convert incoming values to a builder and fold together all builder values.+--+-- Defined as: @foldMap toBuilder@.+--+-- Since 1.0.0+sinkBuilder :: (Monad m, Monoid builder, ToBuilder a builder)+ => Consumer a m builder+sinkBuilder = foldMap toBuilder+{-# INLINE sinkBuilder #-}++-- | Same as @sinkBuilder@, but afterwards convert the builder to its lazy+-- representation.+--+-- Alternatively, this could be considered an alternative to @sinkLazy@, with+-- the following differences:+--+-- * This function will allow multiple input types, not just the strict version+-- of the lazy structure.+--+-- * Some buffer copying may occur in this version.+--+-- Since 1.0.0+sinkLazyBuilder :: (Monad m, Monoid builder, ToBuilder a builder, Builder builder lazy)+ => Consumer a m lazy+sinkLazyBuilder = fmap builderToLazy sinkBuilder+{-# INLINE sinkLazyBuilder #-}++-- | Consume and discard all remaining values in the stream.+--+-- Since 1.0.0+sinkNull :: Monad m => Consumer a m ()+sinkNull = CL.sinkNull+{-# INLINE sinkNull #-}++-- | Same as @await@, but discards any leading 'onull' values.+--+-- Since 1.0.0+awaitNonNull :: (Monad m, NonNull.NonNull b, a ~ NonNull.Nullable b) => Consumer a m (Maybe b)+awaitNonNull =+ go+ where+ go = await >>= maybe (return Nothing) go'++ go' = maybe go (return . Just) . NonNull.fromNullable+{-# INLINE awaitNonNull #-}++-- | Get the next element in the chunked stream.+--+-- Since 1.0.0+headE :: (Monad m, Seq.IsSequence seq) => Consumer seq m (Maybe (Element seq))+headE =+ loop+ where+ loop = await >>= maybe (return Nothing) go+ go x =+ case Seq.uncons x of+ Nothing -> loop+ Just (y, z) -> do+ unless (onull z) $ leftover z+ return $ Just y+{-# INLINE headE #-}++-- | View the next value in the stream without consuming it.+--+-- Since 1.0.0+peek :: Monad m => Consumer a m (Maybe a)+peek = CL.peek+{-# INLINE peek #-}++-- | View the next element in the chunked stream without consuming it.+--+-- Since 1.0.0+peekE :: (Monad m, MonoFoldable mono) => Consumer mono m (Maybe (Element mono))+peekE =+ loop+ where+ loop = await >>= maybe (return Nothing) go+ go x =+ case headMay x of+ Nothing -> loop+ Just y -> do+ leftover x+ return $ Just y+{-# INLINE peekE #-}++-- | Retrieve the last value in the stream, if present.+--+-- Since 1.0.0+last :: Monad m => Consumer a m (Maybe a)+last =+ await >>= maybe (return Nothing) loop+ where+ loop prev = await >>= maybe (return $ Just prev) loop+{-# INLINE last #-}++-- | Retrieve the last element in the chunked stream, if present.+--+-- Since 1.0.0+lastE :: (Monad m, Seq.IsSequence seq) => Consumer seq m (Maybe (Element seq))+lastE =+ awaitNonNull >>= maybe (return Nothing) (loop . NonNull.last . NonNull.asNotEmpty)+ where++ loop prev = awaitNonNull >>= maybe (return $ Just prev) (loop . NonNull.last . NonNull.asNotEmpty)+{-# INLINE lastE #-}++-- | Count how many values are in the stream.+--+-- Since 1.0.0+length :: (Monad m, Num len) => Consumer a m len+length = foldl (\x _ -> x + 1) 0+{-# INLINE length #-}++-- | Count how many elements are in the chunked stream.+--+-- Since 1.0.0+lengthE :: (Monad m, Num len, MonoFoldable mono) => Consumer mono m len+lengthE = foldl (\x y -> x + fromIntegral (olength y)) 0+{-# INLINE lengthE #-}++-- | Get the largest value in the stream, if present.+--+-- Since 1.0.0+maximum :: (Monad m, Ord a) => Consumer a m (Maybe a)+maximum =+ await >>= maybe (return Nothing) loop+ where+ loop prev = await >>= maybe (return $ Just prev) (loop . max prev)+{-# INLINE maximum #-}++-- | Get the largest element in the chunked stream, if present.+--+-- Since 1.0.0+maximumE :: (Monad m, Seq.OrdSequence seq) => Consumer seq m (Maybe (Element seq))+maximumE =+ start+ where+ start = await >>= maybe (return Nothing) start'+ start' x =+ case NonNull.fromNullable x of+ Nothing -> start+ Just y -> loop $ NonNull.maximum $ NonNull.asNotEmpty y+ loop prev = await >>= maybe (return $ Just prev) (loop . ofoldl' max prev)+{-# INLINE maximumE #-}++-- | Get the smallest value in the stream, if present.+--+-- Since 1.0.0+minimum :: (Monad m, Ord a) => Consumer a m (Maybe a)+minimum =+ await >>= maybe (return Nothing) loop+ where+ loop prev = await >>= maybe (return $ Just prev) (loop . min prev)+{-# INLINE minimum #-}++-- | Get the smallest element in the chunked stream, if present.+--+-- Since 1.0.0+minimumE :: (Monad m, Seq.OrdSequence seq) => Consumer seq m (Maybe (Element seq))+minimumE =+ start+ where+ start = await >>= maybe (return Nothing) start'+ start' x =+ case NonNull.fromNullable x of+ Nothing -> start+ Just y -> loop $ NonNull.minimum $ NonNull.asNotEmpty y+ loop prev = await >>= maybe (return $ Just prev) (loop . ofoldl' min prev)+{-# INLINE minimumE #-}++-- | True if there are no values in the stream.+--+-- This function does not modify the stream.+--+-- Since 1.0.0+null :: Monad m => Consumer a m Bool+null = (maybe True (\_ -> False)) `fmap` peek+{-# INLINE null #-}++-- | True if there are no elements in the chunked stream.+--+-- This function may remove empty leading chunks from the stream, but otherwise+-- will not modify it.+--+-- Since 1.0.0+nullE :: (Monad m, MonoFoldable mono)+ => Consumer mono m Bool+nullE =+ go+ where+ go = await >>= maybe (return True) go'+ go' x = if onull x then go else leftover x >> return False+{-# INLINE nullE #-}++-- | Get the sum of all values in the stream.+--+-- Since 1.0.0+sum :: (Monad m, Num a) => Consumer a m a+sum = foldl (+) 0+{-# INLINE sum #-}++-- | Get the sum of all elements in the chunked stream.+--+-- Since 1.0.0+sumE :: (Monad m, MonoFoldable mono, Num (Element mono)) => Consumer mono m (Element mono)+sumE = foldlE (+) 0+{-# INLINE sumE #-}++-- | Get the product of all values in the stream.+--+-- Since 1.0.0+product :: (Monad m, Num a) => Consumer a m a+product = foldl (*) 1+{-# INLINE product #-}++-- | Get the product of all elements in the chunked stream.+--+-- Since 1.0.0+productE :: (Monad m, MonoFoldable mono, Num (Element mono)) => Consumer mono m (Element mono)+productE = foldlE (*) 1+{-# INLINE productE #-}++-- | Find the first matching value.+--+-- Since 1.0.0+find :: Monad m => (a -> Bool) -> Consumer a m (Maybe a)+find f =+ loop+ where+ loop = await >>= maybe (return Nothing) go+ go x = if f x then return (Just x) else loop++-- | Apply the action to all values in the stream.+--+-- Since 1.0.0+mapM_ :: Monad m => (a -> m ()) -> Consumer a m ()+mapM_ = CL.mapM_+{-# INLINE mapM_ #-}++-- | Apply the action to all elements in the chunked stream.+--+-- Since 1.0.0+mapM_E :: (Monad m, MonoFoldable mono) => (Element mono -> m ()) -> Consumer mono m ()+mapM_E = CL.mapM_ . omapM_+{-# INLINE mapM_E #-}++-- | A monadic strict left fold.+--+-- Since 1.0.0+foldM :: Monad m => (a -> b -> m a) -> a -> Consumer b m a+foldM = CL.foldM+{-# INLINE foldM #-}++-- | A monadic strict left fold on a chunked stream.+--+-- Since 1.0.0+foldME :: (Monad m, MonoFoldable mono)+ => (a -> Element mono -> m a)+ -> a+ -> Consumer mono m a+foldME f = foldM (ofoldlM f)+{-# INLINE foldME #-}++-- | Apply the provided monadic mapping function and monoidal combine all values.+--+-- Since 1.0.0+foldMapM :: (Monad m, Monoid w) => (a -> m w) -> Consumer a m w+foldMapM = CL.foldMapM+{-# INLINE foldMapM #-}++-- | Apply the provided monadic mapping function and monoidal combine all+-- elements in the chunked stream.+--+-- Since 1.0.0+foldMapME :: (Monad m, MonoFoldable mono, Monoid w)+ => (Element mono -> m w)+ -> Consumer mono m w+foldMapME f =+ CL.foldM go mempty+ where+ go = ofoldlM (\accum e -> mappend accum `liftM` f e)+{-# INLINE foldMapME #-}++-- | Write all data to the given file.+--+-- This function automatically opens and closes the file handle, and ensures+-- exception safety via @MonadResource. It works for all instances of @IOData@,+-- including @ByteString@ and @Text@.+--+-- Since 1.0.0+sinkFile :: (MonadResource m, IOData a) => FilePath -> Consumer a m ()+sinkFile fp = sinkIOHandle (F.openFile fp SIO.WriteMode)+{-# INLINE sinkFile #-}++-- | Print all incoming values to stdout.+--+-- Since 1.0.0+print :: (Show a, MonadIO m) => Consumer a m ()+print = mapM_ (liftIO . Prelude.print)++-- | @sinkHandle@ applied to @stdout@.+--+-- Since 1.0.0+stdout :: (MonadIO m, IOData a) => Consumer a m ()+stdout = sinkHandle SIO.stdout++-- | @sinkHandle@ applied to @stderr@.+--+-- Since 1.0.0+stderr :: (MonadIO m, IOData a) => Consumer a m ()+stderr = sinkHandle SIO.stderr++-- | Write all data to the given @Handle@.+--+-- Does not close the @Handle@ at any point.+--+-- Since 1.0.0+sinkHandle :: (MonadIO m, IOData a) => Handle -> Consumer a m ()+sinkHandle = CL.mapM_ . hPut+{-# INLINE sinkHandle #-}++-- | Open a @Handle@ using the given function and stream data to it.+--+-- Automatically closes the file at completion.+--+-- Since 1.0.0+sinkIOHandle :: (MonadResource m, IOData a) => SIO.IO Handle -> Consumer a m ()+sinkIOHandle alloc = bracketP alloc SIO.hClose sinkHandle+{-# INLINE sinkIOHandle #-}++-- | Apply a transformation to all values in a stream.+--+-- Since 1.0.0+map :: Monad m => (a -> b) -> Conduit a m b+map = CL.map+{-# INLINE map #-}++-- | Apply a transformation to all elements in a chunked stream.+--+-- Since 1.0.0+mapE :: (Monad m, Functor f) => (a -> b) -> Conduit (f a) m (f b)+mapE = CL.map . fmap+{-# INLINE mapE #-}++-- | Apply a monomorphic transformation to all elements in a chunked stream.+--+-- Unlike @mapE@, this will work on types like @ByteString@ and @Text@ which+-- are @MonoFunctor@ but not @Functor@.+--+-- Since 1.0.0+omapE :: (Monad m, MonoFunctor mono) => (Element mono -> Element mono) -> Conduit mono m mono+omapE = CL.map . omap+{-# INLINE omapE #-}++-- | Apply the function to each value in the stream, resulting in a foldable+-- value (e.g., a list). Then yield each of the individual values in that+-- foldable value separately.+--+-- Generalizes concatMap, mapMaybe, and mapFoldable.+--+-- Since 1.0.0+concatMap :: (Monad m, MonoFoldable mono)+ => (a -> mono)+ -> Conduit a m (Element mono)+concatMap f = awaitForever (yieldMany . f)+{-# INLINE concatMap #-}++-- | Apply the function to each element in the chunked stream, resulting in a+-- foldable value (e.g., a list). Then yield each of the individual values in+-- that foldable value separately.+--+-- Generalizes concatMap, mapMaybe, and mapFoldable.+--+-- Since 1.0.0+concatMapE :: (Monad m, MonoFoldable mono, Monoid w)+ => (Element mono -> w)+ -> Conduit mono m w+concatMapE = CL.map . ofoldMap+{-# INLINE concatMapE #-}++-- | Stream up to n number of values downstream.+--+-- Note that, if downstream terminates early, not all values will be consumed.+-- If you want to force /exactly/ the given number of values to be consumed,+-- see 'takeExactly'.+--+-- Since 1.0.0+take :: Monad m => Int -> Conduit a m a+take =+ loop+ where+ loop count = if count <= 0+ then return ()+ else await >>= maybe (return ()) (\i -> yield i >> loop (count - 1))+{-# INLINE take #-}++-- | Stream up to n number of elements downstream in a chunked stream.+--+-- Note that, if downstream terminates early, not all values will be consumed.+-- If you want to force /exactly/ the given number of values to be consumed,+-- see 'takeExactlyE'.+--+-- Since 1.0.0+takeE :: (Monad m, Seq.IsSequence seq)+ => Seq.Index seq+ -> Conduit seq m seq+takeE =+ loop+ where+ loop i = if i <= 0+ then return ()+ else await >>= maybe (return ()) (go i)++ go i seq = do+ unless (onull x) $ yield x+ unless (onull y) $ leftover y+ loop i'+ where+ (x, y) = Seq.splitAt i seq+ i' = i - fromIntegral (olength x)+{-# INLINEABLE takeE #-}++-- | Stream all values downstream that match the given predicate.+--+-- Same caveats regarding downstream termination apply as with 'take'.+--+-- Since 1.0.0+takeWhile :: Monad m+ => (a -> Bool)+ -> Conduit a m a+takeWhile f =+ loop+ where+ loop = await >>= maybe (return ()) go+ go x = if f x+ then yield x >> loop+ else leftover x+{-# INLINE takeWhile #-}++-- | Stream all elements downstream that match the given predicate in a chunked stream.+--+-- Same caveats regarding downstream termination apply as with 'takeE'.+--+-- Since 1.0.0+takeWhileE :: (Monad m, Seq.IsSequence seq)+ => (Element seq -> Bool)+ -> Conduit seq m seq+takeWhileE f =+ loop+ where+ loop = await >>= maybe (return ()) go++ go seq = do+ unless (onull x) $ yield x+ if onull y+ then loop+ else leftover y+ where+ (x, y) = Seq.span f seq+{-# INLINE takeWhileE #-}++-- | Consume precisely the given number of values and feed them downstream.+--+-- This function is in contrast to 'take', which will only consume up to the+-- given number of values, and will terminate early if downstream terminates+-- early. This function will discard any additional values in the stream if+-- they are unconsumed.+--+-- Note that this function takes a downstream @ConduitM@ as a parameter, as+-- opposed to working with normal fusion. For more information, see+-- <http://www.yesodweb.com/blog/2013/10/core-flaw-pipes-conduit>, the section+-- titled \"pipes and conduit: isolate\".+--+-- Since 1.0.0+takeExactly :: Monad m+ => Int+ -> ConduitM a b m r+ -> ConduitM a b m r+takeExactly count inner = take count =$= do+ r <- inner+ CL.sinkNull+ return r+{-# INLINE takeExactly #-}++-- | Same as 'takeExactly', but for chunked streams.+--+-- Since 1.0.0+takeExactlyE :: (Monad m, Seq.IsSequence a)+ => Seq.Index a+ -> ConduitM a b m r+ -> ConduitM a b m r+takeExactlyE count inner = takeE count =$= do+ r <- inner+ CL.sinkNull+ return r+{-# INLINE takeExactlyE #-}++-- | Flatten out a stream by yielding the values contained in an incoming+-- @MonoFoldable@ as individually yielded values.+--+-- Since 1.0.0+concat :: (Monad m, MonoFoldable mono)+ => Conduit mono m (Element mono)+concat = awaitForever yieldMany+{-# INLINE concat #-}++-- | Keep only values in the stream passing a given predicate.+--+-- Since 1.0.0+filter :: Monad m => (a -> Bool) -> Conduit a m a+filter = CL.filter+{-# INLINE filter #-}++-- | Keep only elements in the chunked stream passing a given predicate.+--+-- Since 1.0.0+filterE :: (Seq.IsSequence seq, Monad m) => (Element seq -> Bool) -> Conduit seq m seq+filterE = CL.map . Seq.filter+{-# INLINE filterE #-}++-- | Map values as long as the result is @Just@.+--+-- Since 1.0.0+mapWhile :: Monad m => (a -> Maybe b) -> Conduit a m b+mapWhile f =+ loop+ where+ loop = await >>= maybe (return ()) go+ go x =+ case f x of+ Just y -> yield y >> loop+ Nothing -> leftover x+{-# INLINE mapWhile #-}++-- | Break up a stream of values into vectors of size n. The final vector may+-- be smaller than n if the total number of values is not a strict multiple of+-- n. No empty vectors will be yielded.+--+-- Since 1.0.0+conduitVector :: (MonadBase base m, V.Vector v a, PrimMonad base)+ => Int -- ^ maximum allowed size+ -> Conduit a m (v a)+conduitVector size =+ loop+ where+ loop = do+ v <- sinkVector size+ unless (V.null v) $ do+ yield v+ loop+{-# INLINE conduitVector #-}++-- | Analog of 'Prelude.scanl' for lists.+--+-- Since 1.0.6+scanl :: Monad m => (a -> b -> a) -> a -> Conduit b m a+scanl f =+ loop+ where+ loop seed =+ await >>= maybe (yield seed) go+ where+ go b = do+ let seed' = f seed b+ seed' `seq` yield seed+ loop seed'+{-# INLINE scanl #-}++-- | 'concatMap' with an accumulator.+--+-- Since 1.0.0+concatMapAccum :: Monad m => (a -> accum -> (accum, [b])) -> accum -> Conduit a m b+concatMapAccum = CL.concatMapAccum+{-# INLINE concatMapAccum #-}++-- | Insert the given value between each two values in the stream.+--+-- Since 1.0.0+intersperse :: Monad m => a -> Conduit a m a+intersperse x =+ await >>= omapM_ go+ where+ go y = yield y >> concatMap (\z -> [x, z])+{-# INLINE intersperse #-}++-- | Apply a monadic transformation to all values in a stream.+--+-- If you do not need the transformed values, and instead just want the monadic+-- side-effects of running the action, see 'mapM_'.+--+-- Since 1.0.0+mapM :: Monad m => (a -> m b) -> Conduit a m b+mapM = CL.mapM+{-# INLINE mapM #-}++-- | Apply a monadic transformation to all elements in a chunked stream.+--+-- Since 1.0.0+mapME :: (Monad m, Data.Traversable.Traversable f) => (a -> m b) -> Conduit (f a) m (f b)+mapME = CL.mapM . Data.Traversable.mapM+{-# INLINE mapME #-}++-- | Apply a monadic monomorphic transformation to all elements in a chunked stream.+--+-- Unlike @mapME@, this will work on types like @ByteString@ and @Text@ which+-- are @MonoFunctor@ but not @Functor@.+--+-- Since 1.0.0+omapME :: (Monad m, MonoTraversable mono)+ => (Element mono -> m (Element mono))+ -> Conduit mono m mono+omapME = CL.mapM . omapM+{-# INLINE omapME #-}++-- | Apply the monadic function to each value in the stream, resulting in a+-- foldable value (e.g., a list). Then yield each of the individual values in+-- that foldable value separately.+--+-- Generalizes concatMapM, mapMaybeM, and mapFoldableM.+--+-- Since 1.0.0+concatMapM :: (Monad m, MonoFoldable mono)+ => (a -> m mono)+ -> Conduit a m (Element mono)+concatMapM f = awaitForever (lift . f >=> yieldMany)+{-# INLINE concatMapM #-}++-- | Keep only values in the stream passing a given monadic predicate.+--+-- Since 1.0.0+filterM :: Monad m+ => (a -> m Bool)+ -> Conduit a m a+filterM f =+ awaitForever go+ where+ go x = do+ b <- lift $ f x+ when b $ yield x+{-# INLINE filterM #-}++-- | Keep only elements in the chunked stream passing a given monadic predicate.+--+-- Since 1.0.0+filterME :: (Monad m, Seq.IsSequence seq) => (Element seq -> m Bool) -> Conduit seq m seq+filterME = CL.mapM . Seq.filterM+{-# INLINE filterME #-}++-- | Apply a monadic action on all values in a stream.+--+-- This @Conduit@ can be used to perform a monadic side-effect for every+-- value, whilst passing the value through the @Conduit@ as-is.+--+-- > iterM f = mapM (\a -> f a >>= \() -> return a)+--+-- Since 1.0.0+iterM :: Monad m => (a -> m ()) -> Conduit a m a+iterM = CL.iterM++-- | Analog of 'Prelude.scanl' for lists, monadic.+--+-- Since 1.0.6+scanlM :: Monad m => (a -> b -> m a) -> a -> Conduit b m a+scanlM f =+ loop+ where+ loop seed =+ await >>= maybe (yield seed) go+ where+ go b = do+ seed' <- lift $ f seed b+ seed' `seq` yield seed+ loop seed'+{-# INLINE scanlM #-}++-- | 'concatMapM' with an accumulator.+--+-- Since 1.0.0+concatMapAccumM :: Monad m => (a -> accum -> m (accum, [b])) -> accum -> Conduit a m b+concatMapAccumM = CL.concatMapAccumM+{-# INLINE concatMapAccumM #-}++-- | Encode a stream of text as UTF8.+--+-- Since 1.0.0+encodeUtf8 :: (Monad m, DTE.Utf8 text binary) => Conduit text m binary+encodeUtf8 = map DTE.encodeUtf8++-- | Decode a stream of binary data as UTF8.+--+-- Since 1.0.0+decodeUtf8 :: MonadThrow m => Conduit ByteString m Text+decodeUtf8 = CT.decode CT.utf8++-- | Stream in the entirety of a single line.+--+-- Like @takeExactly@, this will consume the entirety of the line regardless of+-- the behavior of the inner Conduit.+--+-- Since 1.0.0+line :: (Monad m, Seq.IsSequence seq, Element seq ~ Char)+ => ConduitM seq o m r+ -> ConduitM seq o m r+line inner = do+ loop =$= do+ x <- inner+ sinkNull+ return x+ where+ loop = await >>= omapM_ go+ go t =+ if onull y+ then yield x >> loop+ else do+ unless (onull x) $ yield x+ let y' = Seq.drop 1 y+ unless (onull y') $ leftover y'+ where+ (x, y) = Seq.break (== '\n') t+{-# INLINE line #-}++-- | Same as 'line', but operates on ASCII/binary data.+--+-- Since 1.0.0+lineAscii :: (Monad m, Seq.IsSequence seq, Element seq ~ Word8)+ => ConduitM seq o m r+ -> ConduitM seq o m r+lineAscii inner =+ loop =$= do+ x <- inner+ sinkNull+ return x+ where+ loop = await >>= omapM_ go+ go t =+ if onull y+ then yield x >> loop+ else do+ unless (onull x) $ yield x+ let y' = Seq.drop 1 y+ unless (onull y') $ leftover y'+ where+ (x, y) = Seq.break (== 10) t+{-# INLINE lineAscii #-}++-- | Insert a newline character after each incoming chunk of data.+--+-- Since 1.0.0+unlines :: (Monad m, Seq.IsSequence seq, Element seq ~ Char) => Conduit seq m seq+unlines = concatMap (:[Seq.singleton '\n'])+{-# INLINE unlines #-}++-- | Same as 'unlines', but operates on ASCII/binary data.+--+-- Since 1.0.0+unlinesAscii :: (Monad m, Seq.IsSequence seq, Element seq ~ Word8) => Conduit seq m seq+unlinesAscii = concatMap (:[Seq.singleton 10])+{-# INLINE unlinesAscii #-}++-- | Convert a stream of arbitrarily-chunked textual data into a stream of data+-- where each chunk represents a single line. Note that, if you have+-- unknown/untrusted input, this function is /unsafe/, since it would allow an+-- attacker to form lines of massive length and exhaust memory.+--+-- Since 1.0.0+linesUnbounded :: (Monad m, Seq.IsSequence seq, Element seq ~ Char)+ => Conduit seq m seq+linesUnbounded =+ start+ where+ start = await >>= maybe (return ()) loop++ loop t =+ if onull y+ then do+ mt <- await+ case mt of+ Nothing -> unless (onull t) $ yield t+ Just t' -> loop (t `mappend` t')+ else yield x >> loop (Seq.drop 1 y)+ where+ (x, y) = Seq.break (== '\n') t++-- | Same as 'linesUnbounded', but for ASCII/binary data.+--+-- Since 1.0.0+linesUnboundedAscii :: (Monad m, Seq.IsSequence seq, Element seq ~ Word8)+ => Conduit seq m seq+linesUnboundedAscii =+ start+ where+ start = await >>= maybe (return ()) loop++ loop t =+ if onull y+ then do+ mt <- await+ case mt of+ Nothing -> unless (onull t) $ yield t+ Just t' -> loop (t `mappend` t')+ else yield x >> loop (Seq.drop 1 y)+ where+ (x, y) = Seq.break (== 10) t
+ Data/Conduit/Combinators/Unqualified.hs view
@@ -0,0 +1,1172 @@+-- WARNING: This module is autogenerated+{-# OPTIONS_HADDOCK not-home #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE NoMonomorphismRestriction #-}+module Data.Conduit.Combinators.Unqualified+ ( -- ** Producers+ -- *** Pure+ yieldMany+ , unfoldC+ , enumFromToC+ , iterateC+ , repeatC+ , replicateC+ , sourceLazy++ -- *** Monadic+ , repeatMC+ , repeatWhileMC+ , replicateMC++ -- *** I\/O+ , sourceFile+ , sourceHandle+ , sourceIOHandle+ , stdinC++ -- ** Consumers+ -- *** Pure+ , dropC+ , dropCE+ , dropWhileC+ , dropWhileCE+ , foldC+ , foldCE+ , foldlC+ , foldlCE+ , foldMapC+ , foldMapCE+ , allC+ , allCE+ , anyC+ , anyCE+ , andC+ , andCE+ , orC+ , orCE+ , elemC+ , elemCE+ , notElemC+ , notElemCE+ , sinkLazy+ , sinkList+ , sinkVector+ , sinkBuilder+ , sinkLazyBuilder+ , sinkNull+ , awaitNonNull+ , headCE+ , peekC+ , peekCE+ , lastC+ , lastCE+ , lengthC+ , lengthCE+ , maximumC+ , maximumCE+ , minimumC+ , minimumCE+ , nullC+ , nullCE+ , sumC+ , sumCE+ , productC+ , productCE+ , findC++ -- *** Monadic+ , mapM_C+ , mapM_CE+ , foldMC+ , foldMCE+ , foldMapMC+ , foldMapMCE++ -- *** I\/O+ , sinkFile+ , sinkHandle+ , sinkIOHandle+ , printC+ , stdoutC+ , stderrC++ -- ** Transformers+ -- *** Pure+ , mapC+ , mapCE+ , omapCE+ , concatMapC+ , concatMapCE+ , takeC+ , takeCE+ , takeWhileC+ , takeWhileCE+ , takeExactlyC+ , takeExactlyCE+ , concatC+ , filterC+ , filterCE+ , mapWhileC+ , conduitVector+ , scanlC+ , concatMapAccumC+ , intersperseC++ -- *** Monadic+ , mapMC+ , mapMCE+ , omapMCE+ , concatMapMC+ , filterMC+ , filterMCE+ , iterMC+ , scanlMC+ , concatMapAccumMC++ -- *** Textual+ , encodeUtf8C+ , decodeUtf8C+ , lineC+ , lineAsciiC+ , unlinesC+ , unlinesAsciiC+ , linesUnboundedC+ , linesUnboundedAsciiC+ ) where++-- BEGIN IMPORTS++import qualified Data.Conduit.Combinators as CC+-- BEGIN IMPORTS++import Data.Builder+import qualified Data.NonNull as NonNull+import qualified Data.Traversable+import Control.Applicative ((<$>))+import Control.Category (Category (..))+import Control.Monad (unless, when, (>=>), liftM, forever)+import Control.Monad.Base (MonadBase (liftBase))+import Control.Monad.IO.Class (MonadIO (..))+import Control.Monad.Primitive (PrimMonad)+import Control.Monad.Trans.Class (lift)+import Data.Conduit+import qualified Data.Conduit.List as CL+import Data.IOData+import Data.Monoid (Monoid (..))+import Data.MonoTraversable+import qualified Data.Sequences as Seq+import Data.Sequences.Lazy+import qualified Data.Vector.Generic as V+import qualified Data.Vector.Generic.Mutable as VM+import qualified Filesystem as F+import Filesystem.Path (FilePath)+import Prelude (Bool (..), Eq (..), Int,+ Maybe (..), Monad (..), Num (..),+ Ord (..), fromIntegral, maybe,+ ($), Functor (..), Enum, seq, Show, Char)+import Data.Word (Word8)+import qualified Prelude+import System.IO (Handle)+import qualified System.IO as SIO+import qualified Data.Textual.Encoding as DTE+import qualified Data.Conduit.Text as CT+import Data.ByteString (ByteString)+import Data.Text (Text)+++-- END IMPORTS++-- | Yield each of the values contained by the given @MonoFoldable@.+--+-- This will work on many data structures, including lists, @ByteString@s, and @Vector@s.+--+-- Since 1.0.0+yieldMany :: (Monad m, MonoFoldable mono)+ => mono+ -> Producer m (Element mono)+yieldMany = CC.yieldMany+{-# INLINE yieldMany #-}++-- | Generate a producer from a seed value.+--+-- Since 1.0.0+unfoldC :: Monad m+ => (b -> Maybe (a, b))+ -> b+ -> Producer m a+unfoldC = CC.unfold+{-# INLINE unfoldC #-}++-- | Enumerate from a value to a final value, inclusive, via 'succ'.+--+-- This is generally more efficient than using @Prelude@\'s @enumFromTo@ and+-- combining with @sourceList@ since this avoids any intermediate data+-- structures.+--+-- Since 1.0.0+enumFromToC :: (Monad m, Enum a, Eq a) => a -> a -> Producer m a+enumFromToC = CC.enumFromTo+{-# INLINE enumFromToC #-}++-- | Produces an infinite stream of repeated applications of f to x.+--+-- Since 1.0.0+iterateC :: Monad m => (a -> a) -> a -> Producer m a+iterateC = CC.iterate+{-# INLINE iterateC #-}++-- | Produce an infinite stream consisting entirely of the given value.+--+-- Since 1.0.0+repeatC :: Monad m => a -> Producer m a+repeatC = CC.repeat+{-# INLINE repeatC #-}++-- | Produce a finite stream consisting of n copies of the given value.+--+-- Since 1.0.0+replicateC :: Monad m+ => Int+ -> a+ -> Producer m a+replicateC = CC.replicate+{-# INLINE replicateC #-}++-- | Generate a producer by yielding each of the strict chunks in a @LazySequence@.+--+-- For more information, see 'toChunks'.+--+-- Since 1.0.0+sourceLazy :: (Monad m, LazySequence lazy strict)+ => lazy+ -> Producer m strict+sourceLazy = CC.sourceLazy+{-# INLINE sourceLazy #-}++-- | Repeatedly run the given action and yield all values it produces.+--+-- Since 1.0.0+repeatMC :: Monad m+ => m a+ -> Producer m a+repeatMC = CC.repeatM+{-# INLINE repeatMC #-}++-- | Repeatedly run the given action and yield all values it produces, until+-- the provided predicate returns @False@.+--+-- Since 1.0.0+repeatWhileMC :: Monad m+ => m a+ -> (a -> Bool)+ -> Producer m a+repeatWhileMC = CC.repeatWhileM+{-# INLINE repeatWhileMC #-}++-- | Perform the given action n times, yielding each result.+--+-- Since 1.0.0+replicateMC :: Monad m+ => Int+ -> m a+ -> Producer m a+replicateMC = CC.replicateM+{-# INLINE replicateMC #-}++-- | Read all data from the given file.+--+-- This function automatically opens and closes the file handle, and ensures+-- exception safety via @MonadResource. It works for all instances of @IOData@,+-- including @ByteString@ and @Text@.+--+-- Since 1.0.0+sourceFile :: (MonadResource m, IOData a) => FilePath -> Producer m a+sourceFile = CC.sourceFile+{-# INLINE sourceFile #-}++-- | Read all data from the given @Handle@.+--+-- Does not close the @Handle@ at any point.+--+-- Since 1.0.0+sourceHandle :: (MonadIO m, IOData a) => Handle -> Producer m a+sourceHandle = CC.sourceHandle+{-# INLINE sourceHandle #-}++-- | Open a @Handle@ using the given function and stream data from it.+--+-- Automatically closes the file at completion.+--+-- Since 1.0.0+sourceIOHandle :: (MonadResource m, IOData a) => SIO.IO Handle -> Producer m a+sourceIOHandle = CC.sourceIOHandle+{-# INLINE sourceIOHandle #-}++-- | @sourceHandle@ applied to @stdin@.+--+-- Since 1.0.0+stdinC :: (MonadIO m, IOData a) => Producer m a+stdinC = CC.stdin+{-# INLINE stdinC #-}++-- | Ignore a certain number of values in the stream.+--+-- Since 1.0.0+dropC :: Monad m+ => Int+ -> Consumer a m ()+dropC = CC.drop+{-# INLINE dropC #-}++-- | Drop a certain number of elements from a chunked stream.+--+-- Since 1.0.0+dropCE :: (Monad m, Seq.IsSequence seq)+ => Seq.Index seq+ -> Consumer seq m ()+dropCE = CC.dropE+{-# INLINE dropCE #-}++-- | Drop all values which match the given predicate.+--+-- Since 1.0.0+dropWhileC :: Monad m+ => (a -> Bool)+ -> Consumer a m ()+dropWhileC = CC.dropWhile+{-# INLINE dropWhileC #-}++-- | Drop all elements in the chunked stream which match the given predicate.+--+-- Since 1.0.0+dropWhileCE :: (Monad m, Seq.IsSequence seq)+ => (Element seq -> Bool)+ -> Consumer seq m ()+dropWhileCE = CC.dropWhileE+{-# INLINE dropWhileCE #-}++-- | Monoidally combine all values in the stream.+--+-- Since 1.0.0+foldC :: (Monad m, Monoid a)+ => Consumer a m a+foldC = CC.fold+{-# INLINE foldC #-}++-- | Monoidally combine all elements in the chunked stream.+--+-- Since 1.0.0+foldCE :: (Monad m, MonoFoldable mono, Monoid (Element mono))+ => Consumer mono m (Element mono)+foldCE = CC.foldE+{-# INLINE foldCE #-}++-- | A strict left fold.+--+-- Since 1.0.0+foldlC :: Monad m => (a -> b -> a) -> a -> Consumer b m a+foldlC = CC.foldl+{-# INLINE foldlC #-}++-- | A strict left fold on a chunked stream.+--+-- Since 1.0.0+foldlCE :: (Monad m, MonoFoldable mono)+ => (a -> Element mono -> a)+ -> a+ -> Consumer mono m a+foldlCE = CC.foldlE+{-# INLINE foldlCE #-}++-- | Apply the provided mapping function and monoidal combine all values.+--+-- Since 1.0.0+foldMapC :: (Monad m, Monoid b)+ => (a -> b)+ -> Consumer a m b+foldMapC = CC.foldMap+{-# INLINE foldMapC #-}++-- | Apply the provided mapping function and monoidal combine all elements of the chunked stream.+--+-- Since 1.0.0+foldMapCE :: (Monad m, MonoFoldable mono, Monoid w)+ => (Element mono -> w)+ -> Consumer mono m w+foldMapCE = CC.foldMapE+{-# INLINE foldMapCE #-}++-- | Check that all values in the stream return True.+--+-- Subject to shortcut logic: at the first False, consumption of the stream+-- will stop.+--+-- Since 1.0.0+allC :: Monad m+ => (a -> Bool)+ -> Consumer a m Bool+allC = CC.all+{-# INLINE allC #-}++-- | Check that all elements in the chunked stream return True.+--+-- Subject to shortcut logic: at the first False, consumption of the stream+-- will stop.+--+-- Since 1.0.0+allCE :: (Monad m, MonoFoldable mono)+ => (Element mono -> Bool)+ -> Consumer mono m Bool+allCE = CC.allE+{-# INLINE allCE #-}++-- | Check that at least one value in the stream returns True.+--+-- Subject to shortcut logic: at the first True, consumption of the stream+-- will stop.+--+-- Since 1.0.0+anyC :: Monad m+ => (a -> Bool)+ -> Consumer a m Bool+anyC = CC.any+{-# INLINE anyC #-}++-- | Check that at least one element in the chunked stream returns True.+--+-- Subject to shortcut logic: at the first True, consumption of the stream+-- will stop.+--+-- Since 1.0.0+anyCE :: (Monad m, MonoFoldable mono)+ => (Element mono -> Bool)+ -> Consumer mono m Bool+anyCE = CC.anyE+{-# INLINE anyCE #-}++-- | Are all values in the stream True?+--+-- Consumption stops once the first False is encountered.+--+-- Since 1.0.0+andC :: Monad m => Consumer Bool m Bool+andC = CC.and+{-# INLINE andC #-}++-- | Are all elements in the chunked stream True?+--+-- Consumption stops once the first False is encountered.+--+-- Since 1.0.0+andCE :: (Monad m, MonoFoldable mono, Element mono ~ Bool)+ => Consumer mono m Bool+andCE = CC.andE+{-# INLINE andCE #-}++-- | Are any values in the stream True?+--+-- Consumption stops once the first True is encountered.+--+-- Since 1.0.0+orC :: Monad m => Consumer Bool m Bool+orC = CC.or+{-# INLINE orC #-}++-- | Are any elements in the chunked stream True?+--+-- Consumption stops once the first True is encountered.+--+-- Since 1.0.0+orCE :: (Monad m, MonoFoldable mono, Element mono ~ Bool)+ => Consumer mono m Bool+orCE = CC.orE+{-# INLINE orCE #-}++-- | Are any values in the stream equal to the given value?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+elemC :: (Monad m, Eq a) => a -> Consumer a m Bool+elemC = CC.elem+{-# INLINE elemC #-}++-- | Are any elements in the chunked stream equal to the given element?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+elemCE :: (Monad m, Seq.EqSequence seq)+ => Element seq+ -> Consumer seq m Bool+elemCE = CC.elemE+{-# INLINE elemCE #-}++-- | Are no values in the stream equal to the given value?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+notElemC :: (Monad m, Eq a) => a -> Consumer a m Bool+notElemC = CC.notElem+{-# INLINE notElemC #-}++-- | Are no elements in the chunked stream equal to the given element?+--+-- Stops consuming as soon as a match is found.+--+-- Since 1.0.0+notElemCE :: (Monad m, Seq.EqSequence seq)+ => Element seq+ -> Consumer seq m Bool+notElemCE = CC.notElemE+{-# INLINE notElemCE #-}++-- | Consume all incoming strict chunks into a lazy sequence.+-- Note that the entirety of the sequence will be resident at memory.+--+-- This can be used to consume a stream of strict ByteStrings into a lazy+-- ByteString, for example.+--+-- Since 1.0.0+sinkLazy :: (Monad m, LazySequence lazy strict)+ => Consumer strict m lazy+sinkLazy = CC.sinkLazy+{-# INLINE sinkLazy #-}++-- | Consume all values from the stream and return as a list. Note that this+-- will pull all values into memory.+--+-- Since 1.0.0+sinkList :: Monad m => Consumer a m [a]+sinkList = CC.sinkList+{-# INLINE sinkList #-}++-- | Sink incoming values into a vector, up until size @maxSize@. Subsequent+-- values will be left in the stream. If there are less than @maxSize@ values+-- present, returns a @Vector@ of smaller size.+--+-- Note that using this function is more memory efficient than @sinkList@ and+-- then converting to a @Vector@, as it avoids intermediate list constructors.+--+-- Since 1.0.0+sinkVector :: (MonadBase base m, V.Vector v a, PrimMonad base)+ => Int -- ^ maximum allowed size+ -> Consumer a m (v a)+sinkVector = CC.sinkVector+{-# INLINE sinkVector #-}++-- | Convert incoming values to a builder and fold together all builder values.+--+-- Defined as: @foldMap toBuilder@.+--+-- Since 1.0.0+sinkBuilder :: (Monad m, Monoid builder, ToBuilder a builder)+ => Consumer a m builder+sinkBuilder = CC.sinkBuilder+{-# INLINE sinkBuilder #-}++-- | Same as @sinkBuilder@, but afterwards convert the builder to its lazy+-- representation.+--+-- Alternatively, this could be considered an alternative to @sinkLazy@, with+-- the following differences:+--+-- * This function will allow multiple input types, not just the strict version+-- of the lazy structure.+--+-- * Some buffer copying may occur in this version.+--+-- Since 1.0.0+sinkLazyBuilder :: (Monad m, Monoid builder, ToBuilder a builder, Builder builder lazy)+ => Consumer a m lazy+sinkLazyBuilder = CC.sinkLazyBuilder+{-# INLINE sinkLazyBuilder #-}++-- | Consume and discard all remaining values in the stream.+--+-- Since 1.0.0+sinkNull :: Monad m => Consumer a m ()+sinkNull = CC.sinkNull+{-# INLINE sinkNull #-}++-- | Same as @await@, but discards any leading 'onull' values.+--+-- Since 1.0.0+awaitNonNull :: (Monad m, NonNull.NonNull b, a ~ NonNull.Nullable b) => Consumer a m (Maybe b)+awaitNonNull = CC.awaitNonNull+{-# INLINE awaitNonNull #-}++-- | Get the next element in the chunked stream.+--+-- Since 1.0.0+headCE :: (Monad m, Seq.IsSequence seq) => Consumer seq m (Maybe (Element seq))+headCE = CC.headE+{-# INLINE headCE #-}++-- | View the next value in the stream without consuming it.+--+-- Since 1.0.0+peekC :: Monad m => Consumer a m (Maybe a)+peekC = CC.peek+{-# INLINE peekC #-}++-- | View the next element in the chunked stream without consuming it.+--+-- Since 1.0.0+peekCE :: (Monad m, MonoFoldable mono) => Consumer mono m (Maybe (Element mono))+peekCE = CC.peekE+{-# INLINE peekCE #-}++-- | Retrieve the last value in the stream, if present.+--+-- Since 1.0.0+lastC :: Monad m => Consumer a m (Maybe a)+lastC = CC.last+{-# INLINE lastC #-}++-- | Retrieve the last element in the chunked stream, if present.+--+-- Since 1.0.0+lastCE :: (Monad m, Seq.IsSequence seq) => Consumer seq m (Maybe (Element seq))+lastCE = CC.lastE+{-# INLINE lastCE #-}++-- | Count how many values are in the stream.+--+-- Since 1.0.0+lengthC :: (Monad m, Num len) => Consumer a m len+lengthC = CC.length+{-# INLINE lengthC #-}++-- | Count how many elements are in the chunked stream.+--+-- Since 1.0.0+lengthCE :: (Monad m, Num len, MonoFoldable mono) => Consumer mono m len+lengthCE = CC.lengthE+{-# INLINE lengthCE #-}++-- | Get the largest value in the stream, if present.+--+-- Since 1.0.0+maximumC :: (Monad m, Ord a) => Consumer a m (Maybe a)+maximumC = CC.maximum+{-# INLINE maximumC #-}++-- | Get the largest element in the chunked stream, if present.+--+-- Since 1.0.0+maximumCE :: (Monad m, Seq.OrdSequence seq) => Consumer seq m (Maybe (Element seq))+maximumCE = CC.maximumE+{-# INLINE maximumCE #-}++-- | Get the smallest value in the stream, if present.+--+-- Since 1.0.0+minimumC :: (Monad m, Ord a) => Consumer a m (Maybe a)+minimumC = CC.minimum+{-# INLINE minimumC #-}++-- | Get the smallest element in the chunked stream, if present.+--+-- Since 1.0.0+minimumCE :: (Monad m, Seq.OrdSequence seq) => Consumer seq m (Maybe (Element seq))+minimumCE = CC.minimumE+{-# INLINE minimumCE #-}++-- | True if there are no values in the stream.+--+-- This function does not modify the stream.+--+-- Since 1.0.0+nullC :: Monad m => Consumer a m Bool+nullC = CC.null+{-# INLINE nullC #-}++-- | True if there are no elements in the chunked stream.+--+-- This function may remove empty leading chunks from the stream, but otherwise+-- will not modify it.+--+-- Since 1.0.0+nullCE :: (Monad m, MonoFoldable mono)+ => Consumer mono m Bool+nullCE = CC.nullE+{-# INLINE nullCE #-}++-- | Get the sum of all values in the stream.+--+-- Since 1.0.0+sumC :: (Monad m, Num a) => Consumer a m a+sumC = CC.sum+{-# INLINE sumC #-}++-- | Get the sum of all elements in the chunked stream.+--+-- Since 1.0.0+sumCE :: (Monad m, MonoFoldable mono, Num (Element mono)) => Consumer mono m (Element mono)+sumCE = CC.sumE+{-# INLINE sumCE #-}++-- | Get the product of all values in the stream.+--+-- Since 1.0.0+productC :: (Monad m, Num a) => Consumer a m a+productC = CC.product+{-# INLINE productC #-}++-- | Get the product of all elements in the chunked stream.+--+-- Since 1.0.0+productCE :: (Monad m, MonoFoldable mono, Num (Element mono)) => Consumer mono m (Element mono)+productCE = CC.productE+{-# INLINE productCE #-}++-- | Find the first matching value.+--+-- Since 1.0.0+findC :: Monad m => (a -> Bool) -> Consumer a m (Maybe a)+findC = CC.find+{-# INLINE findC #-}++-- | Apply the action to all values in the stream.+--+-- Since 1.0.0+mapM_C :: Monad m => (a -> m ()) -> Consumer a m ()+mapM_C = CC.mapM_+{-# INLINE mapM_C #-}++-- | Apply the action to all elements in the chunked stream.+--+-- Since 1.0.0+mapM_CE :: (Monad m, MonoFoldable mono) => (Element mono -> m ()) -> Consumer mono m ()+mapM_CE = CC.mapM_E+{-# INLINE mapM_CE #-}++-- | A monadic strict left fold.+--+-- Since 1.0.0+foldMC :: Monad m => (a -> b -> m a) -> a -> Consumer b m a+foldMC = CC.foldM+{-# INLINE foldMC #-}++-- | A monadic strict left fold on a chunked stream.+--+-- Since 1.0.0+foldMCE :: (Monad m, MonoFoldable mono)+ => (a -> Element mono -> m a)+ -> a+ -> Consumer mono m a+foldMCE = CC.foldME+{-# INLINE foldMCE #-}++-- | Apply the provided monadic mapping function and monoidal combine all values.+--+-- Since 1.0.0+foldMapMC :: (Monad m, Monoid w) => (a -> m w) -> Consumer a m w+foldMapMC = CC.foldMapM+{-# INLINE foldMapMC #-}++-- | Apply the provided monadic mapping function and monoidal combine all+-- elements in the chunked stream.+--+-- Since 1.0.0+foldMapMCE :: (Monad m, MonoFoldable mono, Monoid w)+ => (Element mono -> m w)+ -> Consumer mono m w+foldMapMCE = CC.foldMapME+{-# INLINE foldMapMCE #-}++-- | Write all data to the given file.+--+-- This function automatically opens and closes the file handle, and ensures+-- exception safety via @MonadResource. It works for all instances of @IOData@,+-- including @ByteString@ and @Text@.+--+-- Since 1.0.0+sinkFile :: (MonadResource m, IOData a) => FilePath -> Consumer a m ()+sinkFile = CC.sinkFile+{-# INLINE sinkFile #-}++-- | Write all data to the given @Handle@.+--+-- Does not close the @Handle@ at any point.+--+-- Since 1.0.0+sinkHandle :: (MonadIO m, IOData a) => Handle -> Consumer a m ()+sinkHandle = CC.sinkHandle+{-# INLINE sinkHandle #-}++-- | Open a @Handle@ using the given function and stream data to it.+--+-- Automatically closes the file at completion.+--+-- Since 1.0.0+sinkIOHandle :: (MonadResource m, IOData a) => SIO.IO Handle -> Consumer a m ()+sinkIOHandle = CC.sinkIOHandle+{-# INLINE sinkIOHandle #-}++-- | Print all incoming values to stdout.+--+-- Since 1.0.0+printC :: (Show a, MonadIO m) => Consumer a m ()+printC = CC.print+{-# INLINE printC #-}++-- | @sinkHandle@ applied to @stdout@.+--+-- Since 1.0.0+stdoutC :: (MonadIO m, IOData a) => Consumer a m ()+stdoutC = CC.stdout+{-# INLINE stdoutC #-}++-- | @sinkHandle@ applied to @stderr@.+--+-- Since 1.0.0+stderrC :: (MonadIO m, IOData a) => Consumer a m ()+stderrC = CC.stderr+{-# INLINE stderrC #-}++-- | Apply a transformation to all values in a stream.+--+-- Since 1.0.0+mapC :: Monad m => (a -> b) -> Conduit a m b+mapC = CC.map+{-# INLINE mapC #-}++-- | Apply a transformation to all elements in a chunked stream.+--+-- Since 1.0.0+mapCE :: (Monad m, Functor f) => (a -> b) -> Conduit (f a) m (f b)+mapCE = CC.mapE+{-# INLINE mapCE #-}++-- | Apply a monomorphic transformation to all elements in a chunked stream.+--+-- Unlike @mapE@, this will work on types like @ByteString@ and @Text@ which+-- are @MonoFunctor@ but not @Functor@.+--+-- Since 1.0.0+omapCE :: (Monad m, MonoFunctor mono) => (Element mono -> Element mono) -> Conduit mono m mono+omapCE = CC.omapE+{-# INLINE omapCE #-}++-- | Apply the function to each value in the stream, resulting in a foldable+-- value (e.g., a list). Then yield each of the individual values in that+-- foldable value separately.+--+-- Generalizes concatMap, mapMaybe, and mapFoldable.+--+-- Since 1.0.0+concatMapC :: (Monad m, MonoFoldable mono)+ => (a -> mono)+ -> Conduit a m (Element mono)+concatMapC = CC.concatMap+{-# INLINE concatMapC #-}++-- | Apply the function to each element in the chunked stream, resulting in a+-- foldable value (e.g., a list). Then yield each of the individual values in+-- that foldable value separately.+--+-- Generalizes concatMap, mapMaybe, and mapFoldable.+--+-- Since 1.0.0+concatMapCE :: (Monad m, MonoFoldable mono, Monoid w)+ => (Element mono -> w)+ -> Conduit mono m w+concatMapCE = CC.concatMapE+{-# INLINE concatMapCE #-}++-- | Stream up to n number of values downstream.+--+-- Note that, if downstream terminates early, not all values will be consumed.+-- If you want to force /exactly/ the given number of values to be consumed,+-- see 'takeExactly'.+--+-- Since 1.0.0+takeC :: Monad m => Int -> Conduit a m a+takeC = CC.take+{-# INLINE takeC #-}++-- | Stream up to n number of elements downstream in a chunked stream.+--+-- Note that, if downstream terminates early, not all values will be consumed.+-- If you want to force /exactly/ the given number of values to be consumed,+-- see 'takeExactlyE'.+--+-- Since 1.0.0+takeCE :: (Monad m, Seq.IsSequence seq)+ => Seq.Index seq+ -> Conduit seq m seq+takeCE = CC.takeE+{-# INLINE takeCE #-}++-- | Stream all values downstream that match the given predicate.+--+-- Same caveats regarding downstream termination apply as with 'take'.+--+-- Since 1.0.0+takeWhileC :: Monad m+ => (a -> Bool)+ -> Conduit a m a+takeWhileC = CC.takeWhile+{-# INLINE takeWhileC #-}++-- | Stream all elements downstream that match the given predicate in a chunked stream.+--+-- Same caveats regarding downstream termination apply as with 'takeE'.+--+-- Since 1.0.0+takeWhileCE :: (Monad m, Seq.IsSequence seq)+ => (Element seq -> Bool)+ -> Conduit seq m seq+takeWhileCE = CC.takeWhileE+{-# INLINE takeWhileCE #-}++-- | Consume precisely the given number of values and feed them downstream.+--+-- This function is in contrast to 'take', which will only consume up to the+-- given number of values, and will terminate early if downstream terminates+-- early. This function will discard any additional values in the stream if+-- they are unconsumed.+--+-- Note that this function takes a downstream @ConduitM@ as a parameter, as+-- opposed to working with normal fusion. For more information, see+-- <http://www.yesodweb.com/blog/2013/10/core-flaw-pipes-conduit>, the section+-- titled \"pipes and conduit: isolate\".+--+-- Since 1.0.0+takeExactlyC :: Monad m+ => Int+ -> ConduitM a b m r+ -> ConduitM a b m r+takeExactlyC = CC.takeExactly+{-# INLINE takeExactlyC #-}++-- | Same as 'takeExactly', but for chunked streams.+--+-- Since 1.0.0+takeExactlyCE :: (Monad m, Seq.IsSequence a)+ => Seq.Index a+ -> ConduitM a b m r+ -> ConduitM a b m r+takeExactlyCE = CC.takeExactlyE+{-# INLINE takeExactlyCE #-}++-- | Flatten out a stream by yielding the values contained in an incoming+-- @MonoFoldable@ as individually yielded values.+--+-- Since 1.0.0+concatC :: (Monad m, MonoFoldable mono)+ => Conduit mono m (Element mono)+concatC = CC.concat+{-# INLINE concatC #-}++-- | Keep only values in the stream passing a given predicate.+--+-- Since 1.0.0+filterC :: Monad m => (a -> Bool) -> Conduit a m a+filterC = CC.filter+{-# INLINE filterC #-}++-- | Keep only elements in the chunked stream passing a given predicate.+--+-- Since 1.0.0+filterCE :: (Seq.IsSequence seq, Monad m) => (Element seq -> Bool) -> Conduit seq m seq+filterCE = CC.filterE+{-# INLINE filterCE #-}++-- | Map values as long as the result is @Just@.+--+-- Since 1.0.0+mapWhileC :: Monad m => (a -> Maybe b) -> Conduit a m b+mapWhileC = CC.mapWhile+{-# INLINE mapWhileC #-}++-- | Break up a stream of values into vectors of size n. The final vector may+-- be smaller than n if the total number of values is not a strict multiple of+-- n. No empty vectors will be yielded.+--+-- Since 1.0.0+conduitVector :: (MonadBase base m, V.Vector v a, PrimMonad base)+ => Int -- ^ maximum allowed size+ -> Conduit a m (v a)+conduitVector = CC.conduitVector+{-# INLINE conduitVector #-}++-- | Analog of 'Prelude.scanl' for lists.+--+-- Since 1.0.6+scanlC :: Monad m => (a -> b -> a) -> a -> Conduit b m a+scanlC = CC.scanl+{-# INLINE scanlC #-}++-- | 'concatMap' with an accumulator.+--+-- Since 1.0.0+concatMapAccumC :: Monad m => (a -> accum -> (accum, [b])) -> accum -> Conduit a m b+concatMapAccumC = CC.concatMapAccum+{-# INLINE concatMapAccumC #-}++-- | Insert the given value between each two values in the stream.+--+-- Since 1.0.0+intersperseC :: Monad m => a -> Conduit a m a+intersperseC = CC.intersperse+{-# INLINE intersperseC #-}++-- | Apply a monadic transformation to all values in a stream.+--+-- If you do not need the transformed values, and instead just want the monadic+-- side-effects of running the action, see 'mapM_'.+--+-- Since 1.0.0+mapMC :: Monad m => (a -> m b) -> Conduit a m b+mapMC = CC.mapM+{-# INLINE mapMC #-}++-- | Apply a monadic transformation to all elements in a chunked stream.+--+-- Since 1.0.0+mapMCE :: (Monad m, Data.Traversable.Traversable f) => (a -> m b) -> Conduit (f a) m (f b)+mapMCE = CC.mapME+{-# INLINE mapMCE #-}++-- | Apply a monadic monomorphic transformation to all elements in a chunked stream.+--+-- Unlike @mapME@, this will work on types like @ByteString@ and @Text@ which+-- are @MonoFunctor@ but not @Functor@.+--+-- Since 1.0.0+omapMCE :: (Monad m, MonoTraversable mono)+ => (Element mono -> m (Element mono))+ -> Conduit mono m mono+omapMCE = CC.omapME+{-# INLINE omapMCE #-}++-- | Apply the monadic function to each value in the stream, resulting in a+-- foldable value (e.g., a list). Then yield each of the individual values in+-- that foldable value separately.+--+-- Generalizes concatMapM, mapMaybeM, and mapFoldableM.+--+-- Since 1.0.0+concatMapMC :: (Monad m, MonoFoldable mono)+ => (a -> m mono)+ -> Conduit a m (Element mono)+concatMapMC = CC.concatMapM+{-# INLINE concatMapMC #-}++-- | Keep only values in the stream passing a given monadic predicate.+--+-- Since 1.0.0+filterMC :: Monad m+ => (a -> m Bool)+ -> Conduit a m a+filterMC = CC.filterM+{-# INLINE filterMC #-}++-- | Keep only elements in the chunked stream passing a given monadic predicate.+--+-- Since 1.0.0+filterMCE :: (Monad m, Seq.IsSequence seq) => (Element seq -> m Bool) -> Conduit seq m seq+filterMCE = CC.filterME+{-# INLINE filterMCE #-}++-- | Apply a monadic action on all values in a stream.+--+-- This @Conduit@ can be used to perform a monadic side-effect for every+-- value, whilst passing the value through the @Conduit@ as-is.+--+-- > iterM f = mapM (\a -> f a >>= \() -> return a)+--+-- Since 1.0.0+iterMC :: Monad m => (a -> m ()) -> Conduit a m a+iterMC = CC.iterM+{-# INLINE iterMC #-}++-- | Analog of 'Prelude.scanl' for lists, monadic.+--+-- Since 1.0.6+scanlMC :: Monad m => (a -> b -> m a) -> a -> Conduit b m a+scanlMC = CC.scanlM+{-# INLINE scanlMC #-}++-- | 'concatMapM' with an accumulator.+--+-- Since 1.0.0+concatMapAccumMC :: Monad m => (a -> accum -> m (accum, [b])) -> accum -> Conduit a m b+concatMapAccumMC = CC.concatMapAccumM+{-# INLINE concatMapAccumMC #-}++-- | Encode a stream of text as UTF8.+--+-- Since 1.0.0+encodeUtf8C :: (Monad m, DTE.Utf8 text binary) => Conduit text m binary+encodeUtf8C = CC.encodeUtf8+{-# INLINE encodeUtf8C #-}++-- | Decode a stream of binary data as UTF8.+--+-- Since 1.0.0+decodeUtf8C :: MonadThrow m => Conduit ByteString m Text+decodeUtf8C = CC.decodeUtf8+{-# INLINE decodeUtf8C #-}++-- | Stream in the entirety of a single line.+--+-- Like @takeExactly@, this will consume the entirety of the line regardless of+-- the behavior of the inner Conduit.+--+-- Since 1.0.0+lineC :: (Monad m, Seq.IsSequence seq, Element seq ~ Char)+ => ConduitM seq o m r+ -> ConduitM seq o m r+lineC = CC.line+{-# INLINE lineC #-}++-- | Same as 'line', but operates on ASCII/binary data.+--+-- Since 1.0.0+lineAsciiC :: (Monad m, Seq.IsSequence seq, Element seq ~ Word8)+ => ConduitM seq o m r+ -> ConduitM seq o m r+lineAsciiC = CC.lineAscii+{-# INLINE lineAsciiC #-}++-- | Insert a newline character after each incoming chunk of data.+--+-- Since 1.0.0+unlinesC :: (Monad m, Seq.IsSequence seq, Element seq ~ Char) => Conduit seq m seq+unlinesC = CC.unlines+{-# INLINE unlinesC #-}++-- | Same as 'unlines', but operates on ASCII/binary data.+--+-- Since 1.0.0+unlinesAsciiC :: (Monad m, Seq.IsSequence seq, Element seq ~ Word8) => Conduit seq m seq+unlinesAsciiC = CC.unlinesAscii+{-# INLINE unlinesAsciiC #-}++-- | Convert a stream of arbitrarily-chunked textual data into a stream of data+-- where each chunk represents a single line. Note that, if you have+-- unknown/untrusted input, this function is /unsafe/, since it would allow an+-- attacker to form lines of massive length and exhaust memory.+--+-- Since 1.0.0+linesUnboundedC :: (Monad m, Seq.IsSequence seq, Element seq ~ Char)+ => Conduit seq m seq+linesUnboundedC = CC.linesUnbounded+{-# INLINE linesUnboundedC #-}++-- | Same as 'linesUnbounded', but for ASCII/binary data.+--+-- Since 1.0.0+linesUnboundedAsciiC :: (Monad m, Seq.IsSequence seq, Element seq ~ Word8)+ => Conduit seq m seq+linesUnboundedAsciiC = CC.linesUnboundedAscii+{-# INLINE linesUnboundedAsciiC #-}
+ LICENSE view
@@ -0,0 +1,20 @@+The MIT License (MIT)++Copyright (c) 2014 FP Complete++Permission is hereby granted, free of charge, to any person obtaining a copy of+this software and associated documentation files (the "Software"), to deal in+the Software without restriction, including without limitation the rights to+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of+the Software, and to permit persons to whom the Software is furnished to do so,+subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ conduit-combinators.cabal view
@@ -0,0 +1,51 @@+name: conduit-combinators+version: 0.1.0.0+synopsis: Commonly used conduit functions, for both chunked and unchunked data+description: Provides a replacement for Data.Conduit.List, as well as a convenient Conduit module.+homepage: https://github.com/fpco/conduit-combinators+license: MIT+license-file: LICENSE+author: Michael snoyman+maintainer: michael@snoyman.com+category: Data, Conduit+build-type: Simple+cabal-version: >=1.8++library+ exposed-modules: Conduit+ Data.Conduit.Combinators+ other-modules: Data.Conduit.Combinators.Unqualified+ build-depends: base >= 4 && < 5+ , chunked-data+ , conduit >= 1.0.12+ , transformers+ , transformers-base+ , primitive+ , mono-traversable >= 0.3 && < 0.4+ , vector+ , system-fileio+ , system-filepath+ , text+ , bytestring++test-suite test+ hs-source-dirs: test+ main-is: Spec.hs+ type: exitcode-stdio-1.0+ cpp-options: -DTEST+ build-depends: conduit-combinators+ , base+ , hspec >= 1.3+ , basic-prelude+ , text+ , vector+ , transformers+ , chunked-data+ , mono-traversable+ , silently+ , bytestring+ ghc-options: -Wall++source-repository head+ type: git+ location: git://github.com/fpco/conduit-combinators.git
+ test/Spec.hs view
@@ -0,0 +1,502 @@+{-# LANGUAGE NoImplicitPrelude #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns #-}+{-# OPTIONS_GHC -fno-warn-type-defaults #-}+import Conduit+import Test.Hspec+import Test.Hspec.QuickCheck+import BasicPrelude hiding (encodeUtf8)+import qualified Data.Text as T+import qualified Data.Text.Lazy as TL+import Data.IORef+import qualified Data.Vector as V+import qualified Data.Vector.Unboxed as VU+import qualified Data.Vector.Storable as VS+import Control.Monad.Trans.Writer+import qualified Prelude+import qualified System.IO as IO+import Data.Builder+import Data.Sequences.Lazy+import Data.Textual.Encoding+import qualified Data.NonNull as NN+import System.IO.Silently (hCapture)+import GHC.IO.Handle (hDuplicateTo)+import qualified Data.ByteString as S+import qualified Data.ByteString.Char8 as S8++main :: IO ()+main = hspec $ do+ describe "yieldMany" $ do+ it "list" $+ runIdentity (yieldMany [1..10] $$ sinkList)+ `shouldBe` [1..10]+ it "Text" $+ runIdentity (yieldMany ("Hello World" :: Text) $$ sinkList)+ `shouldBe` "Hello World"+ it "unfold" $+ let f 11 = Nothing+ f i = Just (show i, i + 1)+ in runIdentity (unfoldC f 1 $$ sinkList)+ `shouldBe` map show [1..10]+ it "enumFromTo" $+ runIdentity (enumFromToC 1 10 $$ sinkList) `shouldBe` [1..10]+ it "iterate" $+ let f i = i + 1+ src = iterateC f seed+ seed = 1+ count = 10+ res = runIdentity $ src $$ takeC count =$ sinkList+ in res `shouldBe` take count (iterate f seed)+ it "repeat" $+ let src = repeatC seed+ seed = 1+ count = 10+ res = runIdentity $ src $$ takeC count =$ sinkList+ in res `shouldBe` take count (repeat seed)+ it "replicate" $+ let src = replicateC count seed+ seed = 1+ count = 10+ res = runIdentity $ src $$ sinkList+ in res `shouldBe` replicate count seed+ it "sourceLazy" $+ let tss = ["foo", "bar", "baz"]+ tl = TL.fromChunks tss+ res = runIdentity $ sourceLazy tl $$ sinkList+ in res `shouldBe` tss+ it "repeatM" $+ let src = repeatMC (return seed)+ seed = 1+ count = 10+ res = runIdentity $ src $$ takeC count =$ sinkList+ in res `shouldBe` take count (repeat seed)+ it "repeatWhileM" $ do+ ref <- newIORef 0+ let f = atomicModifyIORef ref $ \i -> (succ i, succ i)+ src = repeatWhileMC f (< 11)+ res <- src $$ sinkList+ res `shouldBe` [1..10]+ it "replicateM" $ do+ ref <- newIORef 0+ let f = atomicModifyIORef ref $ \i -> (succ i, succ i)+ src = replicateMC 10 f+ res <- src $$ sinkList+ res `shouldBe` [1..10]+ it "sourceFile" $ do+ let contents = concat $ replicate 10000 $ "this is some content\n"+ fp = "tmp"+ writeFile fp contents+ res <- runResourceT $ sourceFile fp $$ sinkLazy+ res `shouldBe` TL.fromStrict contents+ it "sourceHandle" $ do+ let contents = concat $ replicate 10000 $ "this is some content\n"+ fp = "tmp"+ writeFile fp contents+ res <- IO.withBinaryFile "tmp" IO.ReadMode $ \h -> sourceHandle h $$ sinkLazy+ res `shouldBe` TL.fromStrict contents+ it "sourceIOHandle" $ do+ let contents = concat $ replicate 10000 $ "this is some content\n"+ fp = "tmp"+ writeFile fp contents+ let open = IO.openBinaryFile "tmp" IO.ReadMode+ res <- runResourceT $ sourceIOHandle open $$ sinkLazy+ res `shouldBe` TL.fromStrict contents+ prop "stdin" $ \(S.pack -> content) -> do+ S.writeFile "tmp" content+ IO.withBinaryFile "tmp" IO.ReadMode $ \h -> do+ hDuplicateTo h IO.stdin+ x <- stdinC $$ foldC+ x `shouldBe` content+ prop "drop" $ \(T.pack -> input) count ->+ runIdentity (yieldMany input $$ (dropC count >>= \() -> sinkList))+ `shouldBe` T.unpack (T.drop count input)+ prop "dropE" $ \(T.pack -> input) ->+ runIdentity (yield input $$ (dropCE 5 >>= \() -> foldC))+ `shouldBe` T.drop 5 input+ prop "dropWhile" $ \(T.pack -> input) sep ->+ runIdentity (yieldMany input $$ (dropWhileC (<= sep) >>= \() -> sinkList))+ `shouldBe` T.unpack (T.dropWhile (<= sep) input)+ prop "dropWhileE" $ \(T.pack -> input) sep ->+ runIdentity (yield input $$ (dropWhileCE (<= sep) >>= \() -> foldC))+ `shouldBe` T.dropWhile (<= sep) input+ it "fold" $+ let list = [[1..10], [11..20]]+ src = yieldMany list+ res = runIdentity $ src $$ foldC+ in res `shouldBe` concat list+ it "foldE" $+ let list = [[1..10], [11..20]]+ src = yieldMany $ Identity list+ res = runIdentity $ src $$ foldCE+ in res `shouldBe` concat list+ it "foldl" $+ let res = runIdentity $ yieldMany [1..10] $$ foldlC (+) 0+ in res `shouldBe` sum [1..10]+ it "foldlE" $+ let res = runIdentity $ yield [1..10] $$ foldlCE (+) 0+ in res `shouldBe` sum [1..10]+ it "foldMap" $+ let src = yieldMany [1..10]+ res = runIdentity $ src $$ foldMapC return+ in res `shouldBe` [1..10]+ it "foldMapE" $+ let src = yield [1..10]+ res = runIdentity $ src $$ foldMapCE return+ in res `shouldBe` [1..10]+ prop "all" $ \input -> runIdentity (yieldMany input $$ allC even) `shouldBe` all evenInt input+ prop "allE" $ \input -> runIdentity (yield input $$ allCE even) `shouldBe` all evenInt input+ prop "any" $ \input -> runIdentity (yieldMany input $$ anyC even) `shouldBe` any evenInt input+ prop "anyE" $ \input -> runIdentity (yield input $$ anyCE even) `shouldBe` any evenInt input+ prop "and" $ \input -> runIdentity (yieldMany input $$ andC) `shouldBe` and input+ prop "andE" $ \input -> runIdentity (yield input $$ andCE) `shouldBe` and input+ prop "or" $ \input -> runIdentity (yieldMany input $$ orC) `shouldBe` or input+ prop "orE" $ \input -> runIdentity (yield input $$ orCE) `shouldBe` or input+ prop "elem" $ \x xs -> runIdentity (yieldMany xs $$ elemC x) `shouldBe` elemInt x xs+ prop "elemE" $ \x xs -> runIdentity (yield xs $$ elemCE x) `shouldBe` elemInt x xs+ prop "notElem" $ \x xs -> runIdentity (yieldMany xs $$ notElemC x) `shouldBe` notElemInt x xs+ prop "notElemE" $ \x xs -> runIdentity (yield xs $$ notElemCE x) `shouldBe` notElemInt x xs+ prop "sinkVector regular" $ \xs' -> do+ let maxSize = 20+ xs = take maxSize xs'+ res <- yieldMany xs' $$ sinkVector maxSize+ res `shouldBe` V.fromList (xs :: [Int])+ prop "sinkVector unboxed" $ \xs' -> do+ let maxSize = 20+ xs = take maxSize xs'+ res <- yieldMany xs' $$ sinkVector maxSize+ res `shouldBe` VU.fromList (xs :: [Int])+ prop "sinkVector storable" $ \xs' -> do+ let maxSize = 20+ xs = take maxSize xs'+ res <- yieldMany xs' $$ sinkVector maxSize+ res `shouldBe` VS.fromList (xs :: [Int])+ prop "sinkBuilder" $ \(map T.pack -> inputs) ->+ let builder = runIdentity (yieldMany inputs $$ sinkBuilder) :: TextBuilder+ ltext = builderToLazy builder+ in ltext `shouldBe` fromChunks inputs+ prop "sinkLazyBuilder" $ \(map T.pack -> inputs) ->+ let lbs = runIdentity (yieldMany inputs $$ sinkLazyBuilder)+ in lbs `shouldBe` encodeUtf8 (fromChunks inputs)+ prop "sinkNull" $ \xs toSkip -> do+ res <- yieldMany xs $$ do+ takeC toSkip =$ sinkNull+ sinkList+ res `shouldBe` drop toSkip (xs :: [Int])+ prop "awaitNonNull" $ \xs ->+ fmap (NN.toNullable .NN.asNotEmpty) (runIdentity $ yieldMany xs $$ awaitNonNull)+ `shouldBe` listToMaybe (filter (not . null) (xs :: [[Int]]))+ prop "headE" $ \xs ->+ runIdentity (yieldMany xs $$ ((,) <$> headCE <*> foldC))+ `shouldBe` (listToMaybe $ concat xs, drop 1 $ concat xs :: [Int])+ prop "peek" $ \xs ->+ runIdentity (yieldMany xs $$ ((,) <$> peekC <*> sinkList))+ `shouldBe` (listToMaybe xs, xs :: [Int])+ prop "peekE" $ \xs ->+ runIdentity (yieldMany xs $$ ((,) <$> peekCE <*> foldC))+ `shouldBe` (listToMaybe $ concat xs, concat xs :: [Int])+ prop "last" $ \xs ->+ runIdentity (yieldMany xs $$ lastC)+ `shouldBe` listToMaybe (reverse (xs :: [Int]))+ prop "lastE" $ \xs ->+ runIdentity (yieldMany xs $$ lastCE)+ `shouldBe` listToMaybe (reverse (concat xs :: [Int]))+ prop "length" $ \xs ->+ runIdentity (yieldMany xs $$ lengthC)+ `shouldBe` length (xs :: [Int])+ prop "lengthE" $ \xs ->+ runIdentity (yieldMany xs $$ lengthCE)+ `shouldBe` length (concat xs :: [Int])+ prop "maximum" $ \xs ->+ runIdentity (yieldMany xs $$ maximumC)+ `shouldBe` (if null (xs :: [Int]) then Nothing else Just (maximum xs))+ prop "maximumE" $ \xs ->+ runIdentity (yieldMany xs $$ maximumCE)+ `shouldBe` (if null (concat xs :: [Int]) then Nothing else Just (maximum $ concat xs))+ prop "minimum" $ \xs ->+ runIdentity (yieldMany xs $$ minimumC)+ `shouldBe` (if null (xs :: [Int]) then Nothing else Just (minimum xs))+ prop "minimumE" $ \xs ->+ runIdentity (yieldMany xs $$ minimumCE)+ `shouldBe` (if null (concat xs :: [Int]) then Nothing else Just (minimum $ concat xs))+ prop "null" $ \xs ->+ runIdentity (yieldMany xs $$ nullC)+ `shouldBe` null (xs :: [Int])+ prop "nullE" $ \xs ->+ runIdentity (yieldMany xs $$ ((,) <$> nullCE <*> foldC))+ `shouldBe` (null (concat xs :: [Int]), concat xs)+ prop "sum" $ \xs ->+ runIdentity (yieldMany xs $$ sumC)+ `shouldBe` sum (xs :: [Int])+ prop "sumE" $ \xs ->+ runIdentity (yieldMany xs $$ sumCE)+ `shouldBe` sum (concat xs :: [Int])+ prop "product" $ \xs ->+ runIdentity (yieldMany xs $$ productC)+ `shouldBe` product (xs :: [Int])+ prop "productE" $ \xs ->+ runIdentity (yieldMany xs $$ productCE)+ `shouldBe` product (concat xs :: [Int])+ prop "find" $ \x xs ->+ runIdentity (yieldMany xs $$ findC (< x))+ `shouldBe` find (< x) (xs :: [Int])+ prop "mapM_" $ \xs ->+ let res = execWriter $ yieldMany xs $$ mapM_C (tell . return)+ in res `shouldBe` (xs :: [Int])+ prop "mapM_E" $ \xs ->+ let res = execWriter $ yield xs $$ mapM_CE (tell . return)+ in res `shouldBe` (xs :: [Int])+ prop "foldM" $ \xs -> do+ res <- yieldMany xs $$ foldMC addM 0+ res `shouldBe` sum xs+ prop "foldME" $ \xs -> do+ res <- yield xs $$ foldMCE addM 0+ res `shouldBe` sum xs+ it "foldMapM" $+ let src = yieldMany [1..10]+ res = runIdentity $ src $$ foldMapMC (return . return)+ in res `shouldBe` [1..10]+ it "foldMapME" $+ let src = yield [1..10]+ res = runIdentity $ src $$ foldMapMCE (return . return)+ in res `shouldBe` [1..10]+ it "sinkFile" $ do+ let contents = concat $ replicate 1000 $ "this is some content\n"+ fp = "tmp"+ runResourceT $ yield contents $$ sinkFile fp+ res <- readFile fp+ res `shouldBe` contents+ it "sinkHandle" $ do+ let contents = concat $ replicate 1000 $ "this is some content\n"+ fp = "tmp"+ IO.withBinaryFile "tmp" IO.WriteMode $ \h -> yield contents $$ sinkHandle h+ res <- readFile fp+ res `shouldBe` contents+ it "sinkIOHandle" $ do+ let contents = concat $ replicate 1000 $ "this is some content\n"+ fp = "tmp"+ open = IO.openBinaryFile "tmp" IO.WriteMode+ runResourceT $ yield contents $$ sinkIOHandle open+ res <- readFile fp+ res `shouldBe` contents+ prop "print" $ \vals -> do+ let expected = Prelude.unlines $ map showInt vals+ (actual, ()) <- hCapture [IO.stdout] $ yieldMany vals $$ printC+ actual `shouldBe` expected+ prop "stdout" $ \vals -> do+ let expected = concat vals+ (actual, ()) <- hCapture [IO.stdout] $ yieldMany vals $$ stdoutC+ actual `shouldBe` expected+ prop "stderr" $ \vals -> do+ let expected = concat vals+ (actual, ()) <- hCapture [IO.stderr] $ yieldMany vals $$ stderrC+ actual `shouldBe` expected+ prop "map" $ \input ->+ runIdentity (yieldMany input $$ mapC succChar =$ sinkList)+ `shouldBe` map succChar input+ prop "mapE" $ \(map V.fromList -> inputs) ->+ runIdentity (yieldMany inputs $$ mapCE succChar =$ foldC)+ `shouldBe` V.map succChar (V.concat inputs)+ prop "omapE" $ \(map T.pack -> inputs) ->+ runIdentity (yieldMany inputs $$ omapCE succChar =$ foldC)+ `shouldBe` T.map succChar (T.concat inputs)+ prop "concatMap" $ \input ->+ runIdentity (yieldMany input $$ concatMapC showInt =$ sinkList)+ `shouldBe` concatMap showInt input+ prop "concatMapE" $ \input ->+ runIdentity (yield input $$ concatMapCE showInt =$ foldC)+ `shouldBe` concatMap showInt input+ prop "take" $ \(T.pack -> input) count ->+ runIdentity (yieldMany input $$ (takeC count >>= \() -> mempty) =$ sinkList)+ `shouldBe` T.unpack (T.take count input)+ prop "takeE" $ \(T.pack -> input) count ->+ runIdentity (yield input $$ (takeCE count >>= \() -> mempty) =$ foldC)+ `shouldBe` T.take count input+ prop "takeWhile" $ \(T.pack -> input) sep ->+ runIdentity (yieldMany input $$ do+ x <- (takeWhileC (<= sep) >>= \() -> mempty) =$ sinkList+ y <- sinkList+ return (x, y))+ `shouldBe` span (<= sep) (T.unpack input)+ prop "takeWhileE" $ \(T.pack -> input) sep ->+ runIdentity (yield input $$ do+ x <- (takeWhileCE (<= sep) >>= \() -> mempty) =$ foldC+ y <- foldC+ return (x, y))+ `shouldBe` T.span (<= sep) input+ it "takeExactly" $+ let src = yieldMany [1..10]+ sink = do+ x <- takeExactlyC 5 $ return 1+ y <- sinkList+ return (x, y)+ res = runIdentity $ src $$ sink+ in res `shouldBe` (1, [6..10])+ it "takeExactlyE" $+ let src = yield ("Hello World" :: Text)+ sink = do+ takeExactlyCE 5 (mempty :: Sink Text Identity ())+ y <- sinkLazy+ return y+ res = runIdentity $ src $$ sink+ in res `shouldBe` " World"+ it "takeExactlyE Vector" $ do+ let src = yield (V.fromList $ T.unpack "Hello World")+ sink = do+ x <- takeExactlyCE 5 $ return 1+ y <- foldC+ return (x, y)+ res <- src $$ sink+ res `shouldBe` (1, V.fromList $ T.unpack " World")+ it "takeExactlyE 2" $+ let src = yield ("Hello World" :: Text)+ sink = do+ x <- takeExactlyCE 5 $ return 1+ y <- sinkLazy+ return (x, y)+ res = runIdentity $ src $$ sink+ -- FIXME type signature on next line is necessary in GHC 7.6.3 to+ -- avoid a crash:+ --+ -- test: internal error: ARR_WORDS object entered!+ -- (GHC version 7.6.3 for x86_64_unknown_linux)+ -- Please report this as a GHC bug: http://www.haskell.org/ghc/reportabug+ -- Aborted (core dumped)+ --+ -- Report upstream when packages are released+ in res `shouldBe` (1, " World" :: LText)+ prop "concat" $ \input ->+ runIdentity (yield (T.pack input) $$ concatC =$ sinkList)+ `shouldBe` input+ prop "filter" $ \input ->+ runIdentity (yieldMany input $$ filterC evenInt =$ sinkList)+ `shouldBe` filter evenInt input+ prop "filterE" $ \input ->+ runIdentity (yield input $$ filterCE evenInt =$ foldC)+ `shouldBe` filter evenInt input+ prop "mapWhile" $ \input (min 20 -> highest) ->+ let f i =+ if i < highest+ then Just (i + 2 :: Int)+ else Nothing+ res = runIdentity $ yieldMany input $$ do+ x <- (mapWhileC f >>= \() -> mempty) =$ sinkList+ y <- sinkList+ return (x, y)+ expected = (map (+ 2) $ takeWhile (< highest) input, dropWhile (< highest) input)+ in res `shouldBe` expected+ prop "conduitVector" $ \(take 200 -> input) size' -> do+ let size = min 30 $ succ $ abs size'+ res <- yieldMany input $$ conduitVector size =$ sinkList+ res `shouldSatisfy` all (\v -> V.length v <= size)+ drop 1 (reverse res) `shouldSatisfy` all (\v -> V.length v == size)+ V.concat res `shouldBe` V.fromList (input :: [Int])+ prop "scanl" $ \input seed ->+ let f a b = a + b :: Int+ res = runIdentity $ yieldMany input $$ scanlC f seed =$ sinkList+ in res `shouldBe` scanl f seed input+ it "concatMapAccum" $+ let f a accum = (a + accum, [a, accum])+ res = runIdentity $ yieldMany [1..3] $$ concatMapAccumC f 0 =$ sinkList+ in res `shouldBe` [1, 0, 2, 1, 3, 3]+ prop "intersperse" $ \xs x ->+ runIdentity (yieldMany xs $$ intersperseC x =$ sinkList)+ `shouldBe` intersperse (x :: Int) xs+ prop "mapM" $ \input ->+ runIdentity (yieldMany input $$ mapMC (return . succChar) =$ sinkList)+ `shouldBe` map succChar input+ prop "mapME" $ \(map V.fromList -> inputs) ->+ runIdentity (yieldMany inputs $$ mapMCE (return . succChar) =$ foldC)+ `shouldBe` V.map succChar (V.concat inputs)+ prop "omapME" $ \(map T.pack -> inputs) ->+ runIdentity (yieldMany inputs $$ omapMCE (return . succChar) =$ foldC)+ `shouldBe` T.map succChar (T.concat inputs)+ prop "concatMapM" $ \input ->+ runIdentity (yieldMany input $$ concatMapMC (return . showInt) =$ sinkList)+ `shouldBe` concatMap showInt input+ prop "filterM" $ \input ->+ runIdentity (yieldMany input $$ filterMC (return . evenInt) =$ sinkList)+ `shouldBe` filter evenInt input+ prop "filterME" $ \input ->+ runIdentity (yield input $$ filterMCE (return . evenInt) =$ foldC)+ `shouldBe` filter evenInt input+ prop "iterM" $ \input -> do+ (x, y) <- runWriterT $ yieldMany input $$ iterMC (tell . return) =$ sinkList+ x `shouldBe` (input :: [Int])+ y `shouldBe` input+ prop "scanlM" $ \input seed ->+ let f a b = a + b :: Int+ fm a b = return $ a + b+ res = runIdentity $ yieldMany input $$ scanlMC fm seed =$ sinkList+ in res `shouldBe` scanl f seed input+ it "concatMapAccumM" $+ let f a accum = return (a + accum, [a, accum])+ res = runIdentity $ yieldMany [1..3] $$ concatMapAccumMC f 0 =$ sinkList+ in res `shouldBe` [1, 0, 2, 1, 3, 3]+ prop "encode UTF8" $ \(map T.pack -> inputs) -> do+ let expected = encodeUtf8 $ fromChunks inputs+ actual <- yieldMany inputs+ $$ encodeUtf8C+ =$ sinkLazy+ actual `shouldBe` expected+ prop "encode/decode UTF8" $ \(map T.pack -> inputs) (min 50 . max 1 . abs -> chunkSize) -> do+ let expected = fromChunks inputs+ actual <- yieldMany inputs+ $$ encodeUtf8C+ =$ concatC+ =$ conduitVector chunkSize+ =$ mapC (S.pack . V.toList)+ =$ decodeUtf8C+ =$ sinkLazy+ actual `shouldBe` expected+ prop "line" $ \(map T.pack -> input) size ->+ let src = yieldMany input+ sink = do+ x <- lineC $ takeCE size =$ foldC+ y <- foldC+ return (x, y)+ res = runIdentity $ src $$ sink+ expected =+ let (x, y) = T.break (== '\n') (T.concat input)+ in (T.take size x, T.drop 1 y)+ in res `shouldBe` expected+ prop "lineAscii" $ \(map S.pack -> input) size ->+ let src = yieldMany input+ sink = do+ x <- lineAsciiC $ takeCE size =$ foldC+ y <- foldC+ return (x, y)+ res = runIdentity $ src $$ sink+ expected =+ let (x, y) = S.break (== 10) (S.concat input)+ in (S.take size x, S.drop 1 y)+ in res `shouldBe` expected+ prop "unlines" $ \(map T.pack -> input) ->+ runIdentity (yieldMany input $$ unlinesC =$ foldC)+ `shouldBe` T.unlines input+ prop "unlinesAscii" $ \(map S.pack -> input) ->+ runIdentity (yieldMany input $$ unlinesAsciiC =$ foldC)+ `shouldBe` S8.unlines input+ prop "linesUnbounded" $ \(map T.pack -> input) ->+ runIdentity (yieldMany input $$ (linesUnboundedC >>= \() -> mempty) =$ sinkList)+ `shouldBe` T.lines (T.concat input)+ prop "linesUnboundedAscii" $ \(map S.pack -> input) ->+ runIdentity (yieldMany input $$ (linesUnboundedAsciiC >>= \() -> mempty) =$ sinkList)+ `shouldBe` S8.lines (S.concat input)++evenInt :: Int -> Bool+evenInt = even++elemInt :: Int -> [Int] -> Bool+elemInt = elem++notElemInt :: Int -> [Int] -> Bool+notElemInt = notElem++addM :: Monad m => Int -> Int -> m Int+addM x y = return (x + y)++succChar :: Char -> Char+succChar = succ++showInt :: Int -> String+showInt = Prelude.show