-- | -- Module: Data.Enumerator -- Copyright: 2010-2011 John Millikin -- License: MIT -- -- Maintainer: jmillikin@gmail.com -- Portability: portable -- -- Core enumerator types, and some useful primitives. -- -- This module is intended to be imported qualified: -- -- @ -- import qualified Data.Enumerator as E -- @ module Data.Enumerator ( -- * Types Stream (..) , Iteratee (..) , Step (..) , Enumerator , Enumeratee -- * Primitives , returnI , continue , yield -- ** Operators , (>>==) , (==<<) , ($$) , (>==>) , (<==<) , (=$) , ($=) -- ** Running iteratees , run , run_ -- ** Error handling , throwError , catchError -- * Miscellaneous , concatEnums , joinI , joinE , Data.Enumerator.sequence , enumEOF , checkContinue0 , checkContinue1 , checkDoneEx , checkDone , isEOF , tryIO -- ** Testing and debugging , printChunks , enumList -- * Legacy compatibility -- ** Obsolete , liftTrans , liftI , peek , Data.Enumerator.last , Data.Enumerator.length -- ** Aliases , Data.Enumerator.head , Data.Enumerator.drop , Data.Enumerator.dropWhile , Data.Enumerator.span , Data.Enumerator.break , consume , Data.Enumerator.foldl , Data.Enumerator.foldl' , foldM , Data.Enumerator.iterate , iterateM , Data.Enumerator.repeat , repeatM , Data.Enumerator.replicate , replicateM , generateM , Data.Enumerator.map , Data.Enumerator.mapM , Data.Enumerator.concatMap , concatMapM , Data.Enumerator.filter , filterM , liftFoldL , liftFoldL' , liftFoldM ) where import Control.Applicative as A import qualified Control.Exception as Exc import qualified Control.Monad as CM import Control.Monad.IO.Class (MonadIO, liftIO) import Control.Monad.Trans.Class (MonadTrans, lift) import Data.Function (fix) import Data.List (genericLength, genericSplitAt) import Data.Monoid (Monoid, mempty, mappend, mconcat) import Data.Typeable ( Typeable, typeOf , Typeable1, typeOf1 , mkTyConApp, mkTyCon) import {-# SOURCE #-} qualified Data.Enumerator.List as EL -- | A 'Stream' is a sequence of chunks generated by an 'Enumerator'. -- -- @('Chunks' [])@ is used to indicate that a stream is still active, but -- currently has no available data. Iteratees should ignore empty chunks. data Stream a = Chunks [a] | EOF deriving (Show, Eq) instance Monad Stream where return = Chunks . return Chunks xs >>= f = mconcat (fmap f xs) EOF >>= _ = EOF instance Monoid (Stream a) where mempty = Chunks mempty mappend (Chunks xs) (Chunks ys) = Chunks (xs ++ ys) mappend _ _ = EOF data Step a m b -- | The 'Iteratee' is capable of accepting more input. Note that more input -- is not necessarily required; the 'Iteratee' might be able to generate a -- value immediately if it receives 'EOF'. = Continue (Stream a -> Iteratee a m b) -- | The 'Iteratee' cannot receive any more input, and has generated a -- result. Included in this value is left-over input, which can be passed to -- composed 'Iteratee's. | Yield b (Stream a) -- | The 'Iteratee' encountered an error which prevents it from proceeding -- further. | Error Exc.SomeException -- | The primary data type for this library, which consumes -- input from a 'Stream' until it either generates a value or encounters -- an error. Rather than requiring all input at once, an iteratee will -- return 'Continue' when it is capable of processing more data. -- -- In general, iteratees begin in the 'Continue' state. As each chunk is -- passed to the continuation, the iteratee returns the next step: -- 'Continue' for more data, 'Yield' when it's finished, or 'Error' to -- abort processing. newtype Iteratee a m b = Iteratee { runIteratee :: m (Step a m b) } instance Monad m => Monad (Iteratee a m) where return x = yield x (Chunks []) m0 >>= f = ($ m0) $ fix $ \bind m -> Iteratee $ runIteratee m >>= \r1 -> case r1 of Continue k -> return (Continue (bind . k)) Error err -> return (Error err) Yield x (Chunks []) -> runIteratee (f x) Yield x extra -> runIteratee (f x) >>= \r2 -> case r2 of Continue k -> runIteratee (k extra) Error err -> return (Error err) Yield x' _ -> return (Yield x' extra) instance MonadTrans (Iteratee a) where lift m = Iteratee (m >>= runIteratee . return) instance MonadIO m => MonadIO (Iteratee a m) where liftIO = lift . liftIO -- | While 'Iteratee's consume data, enumerators generate it. Since -- @'Iteratee'@ is an alias for @m ('Step' a m b)@, 'Enumerator's can -- be considered step transformers of type -- @'Step' a m b -> m ('Step' a m b)@. -- -- 'Enumerator's typically read from an external source (parser, handle, -- random generator, etc). They feed chunks into an 'Iteratee' until the -- source runs out of data (triggering 'EOF') or the iteratee finishes -- processing ('Yield's a value). type Enumerator a m b = Step a m b -> Iteratee a m b -- | In cases where an enumerator acts as both a source and sink, the resulting -- type is named an 'Enumeratee'. Enumeratees have two input types, -- “outer a” (@aOut@) and “inner a” (@aIn@). type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b) -- | Since: 0.4.8 instance Typeable1 Stream where typeOf1 _ = mkTyConApp tyCon [] where tyCon = mkTyCon "Data.Enumerator.Stream" -- | Since: 0.4.6 instance (Typeable a, Typeable1 m) => Typeable1 (Iteratee a m) where typeOf1 i = let tyCon = mkTyCon "Data.Enumerator.Iteratee" (a, m) = peel i peel :: Iteratee a m b -> (a, m ()) peel = undefined in mkTyConApp tyCon [typeOf a, typeOf1 m] -- | Since: 0.4.8 instance (Typeable a, Typeable1 m) => Typeable1 (Step a m) where typeOf1 s = let tyCon = mkTyCon "Data.Enumerator.Step" (a, m) = peel s peel :: Step a m b -> (a, m ()) peel = undefined in mkTyConApp tyCon [typeOf a, typeOf1 m] instance Monad m => Functor (Iteratee a m) where fmap = CM.liftM instance Monad m => A.Applicative (Iteratee a m) where pure = return (<*>) = CM.ap instance Functor Stream where fmap f (Chunks xs) = Chunks (fmap f xs) fmap _ EOF = EOF -- | Since: 0.4.5 instance A.Applicative Stream where pure = return (<*>) = CM.ap -- | @'returnI' step = 'Iteratee' (return step)@ returnI :: Monad m => Step a m b -> Iteratee a m b returnI step = Iteratee (return step) -- | @'yield' x extra = 'returnI' ('Yield' x extra)@ -- -- WARNING: due to the current encoding of iteratees in this library, -- careless use of the 'yield' primitive may violate the monad laws. -- To prevent this, always make sure that an iteratee never yields -- extra data unless it has received at least one input element. -- -- More strictly, iteratees may not yield data that they did not -- receive as input. Don't use 'yield' to “inject” elements -- into the stream. yield :: Monad m => b -> Stream a -> Iteratee a m b yield x extra = returnI (Yield x extra) -- | @'continue' k = 'returnI' ('Continue' k)@ continue :: Monad m => (Stream a -> Iteratee a m b) -> Iteratee a m b continue k = returnI (Continue k) -- | Run an iteratee until it finishes, and return either the final value -- (if it succeeded) or the error (if it failed). run :: Monad m => Iteratee a m b -> m (Either Exc.SomeException b) run i = do mStep <- runIteratee $ enumEOF ==<< i case mStep of Error err -> return $ Left err Yield x _ -> return $ Right x Continue _ -> error "run: divergent iteratee" -- | Like 'run', except errors are converted to exceptions and thrown. -- Primarily useful for small scripts or other simple cases. -- -- Since: 0.4.1 run_ :: Monad m => Iteratee a m b -> m b run_ i = run i >>= either Exc.throw return -- | @'throwError' exc = 'returnI' ('Error' ('Exc.toException' exc))@ throwError :: (Monad m, Exc.Exception e) => e -> Iteratee a m b throwError exc = returnI (Error (Exc.toException exc)) -- | Runs the iteratee, and calls an exception handler if an 'Error' is -- returned. By handling errors within the enumerator library, and requiring -- all errors to be represented by 'Exc.SomeException', libraries with -- varying error types can be easily composed. -- -- WARNING: after a few rounds of "catchError doesn't work because X", this -- function has grown into a horrible monster. I have no concept of what -- unexpected behaviors lurk in its dark crevices. Users are strongly advised -- to wrap all uses of @catchError@ with an appropriate @isolate@, such as -- @Data.Enumerator.List.isolate@ or @Data.Enumerator.Binary.isolate@, which -- will handle input framing even in the face of unexpected errors. -- -- Within the error handler, it is difficult or impossible to know how much -- input the original iteratee has consumed. -- -- Since: 0.1.1 catchError :: Monad m => Iteratee a m b -> (Exc.SomeException -> Iteratee a m b) -> Iteratee a m b catchError i h = go i where go iter = Iteratee $ do step <- runIteratee iter case step of Yield _ _ -> return step Error err -> runIteratee (h err) Continue k -> return (Continue (wrap k)) wrap k EOF = Iteratee $ do res <- run (k EOF) case res of Left err -> runIteratee (enumEOF $$ h err) Right b -> return (Yield b EOF) wrap k stream = Iteratee $ do step <- runIteratee (k stream) case step of Yield _ _ -> return step Error err -> do step' <- runIteratee (h err) case step' of Continue k' -> runIteratee (k' stream) _ -> return step' Continue k' -> return (Continue (wrap k')) infixl 1 >>== infixr 1 ==<< infixr 0 $$ infixr 1 >==> infixr 1 <==< -- | Equivalent to '(>>=)' for @m ('Step' a m b)@; allows 'Iteratee's with -- different input types to be composed. (>>==) :: Monad m => Iteratee a m b -> (Step a m b -> Iteratee a' m b') -> Iteratee a' m b' i >>== f = Iteratee (runIteratee i >>= runIteratee . f) -- | @'(==\<\<)' = flip '(\>\>==)'@ (==<<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b' (==<<) = flip (>>==) -- | @'($$)' = '(==\<\<)'@ -- -- This might be easier to read when passing a chain of iteratees to an -- enumerator. -- -- Since: 0.1.1 ($$) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b' ($$) = (==<<) -- | @'(>==>)' e1 e2 s = e1 s '>>==' e2@ -- -- Since: 0.1.1 (>==>) :: Monad m => Enumerator a m b -> (Step a m b -> Iteratee a' m b') -> Step a m b -> Iteratee a' m b' (>==>) e1 e2 s = e1 s >>== e2 -- | @'(\<==\<)' = flip '(>==>)'@ -- -- Since: 0.1.1 (<==<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Enumerator a m b -> Step a m b -> Iteratee a' m b' (<==<) = flip (>==>) -- | Print chunks as they're received from the enumerator, optionally -- printing empty chunks. printChunks :: (MonadIO m, Show a) => Bool -- ^ Print empty chunks -> Iteratee a m () printChunks printEmpty = continue loop where loop (Chunks xs) = do let hide = null xs && not printEmpty CM.unless hide (liftIO (print xs)) continue loop loop EOF = do liftIO (putStrLn "EOF") yield () EOF -- | @'enumList' n xs@ enumerates /xs/ as a stream, passing /n/ inputs per -- chunk. -- -- Primarily useful for testing and debugging. enumList :: Monad m => Integer -> [a] -> Enumerator a m b enumList n = loop where loop xs (Continue k) | not (null xs) = let (s1, s2) = genericSplitAt n xs in k (Chunks s1) >>== loop s2 loop _ step = returnI step -- | Compose a list of 'Enumerator's using @'(>>==)'@ concatEnums :: Monad m => [Enumerator a m b] -> Enumerator a m b concatEnums = Prelude.foldl (>==>) returnI -- | 'joinI' is used to “flatten” 'Enumeratee's into an -- 'Iteratee'. joinI :: Monad m => Iteratee a m (Step a' m b) -> Iteratee a m b joinI outer = outer >>= check where check (Continue k) = k EOF >>== \s -> case s of Continue _ -> error "joinI: divergent iteratee" _ -> check s check (Yield x _) = return x check (Error e) = throwError e infixr 0 =$ -- | @enum =$ iter = 'joinI' (enum $$ iter)@ -- -- “Wraps” an iteratee /inner/ in an enumeratee /wrapper/. -- The resulting iteratee will consume /wrapper/’s input type and -- yield /inner/’s output type. -- -- Note: if the inner iteratee yields leftover input when it finishes, -- that extra will be discarded. -- -- As an example, consider an iteratee that converts a stream of UTF8-encoded -- bytes into a single 'TL.Text': -- -- > consumeUTF8 :: Monad m => Iteratee ByteString m Text -- -- It could be written with either 'joinI' or '(=$)': -- -- > import Data.Enumerator.Text as ET -- > -- > consumeUTF8 = joinI (decode utf8 $$ ET.consume) -- > consumeUTF8 = decode utf8 =$ ET.consume -- -- Since: 0.4.9 (=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b enum =$ iter = joinI (enum $$ iter) -- | Flatten an enumerator/enumeratee pair into a single enumerator. joinE :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b joinE enum enee s = Iteratee $ do step <- runIteratee (enumEOF $$ enum $$ enee s) case step of Error err -> return (Error err) Yield x _ -> return x Continue _ -> error "joinE: divergent iteratee" infixr 0 $= -- | @enum $= enee = 'joinE' enum enee@ -- -- “Wraps” an enumerator /inner/ in an enumeratee /wrapper/. -- The resulting enumerator will generate /wrapper/’s output type. -- -- As an example, consider an enumerator that yields line character counts -- for a text file (e.g. for source code readability checking): -- -- > enumFileCounts :: FilePath -> Enumerator Int IO b -- -- It could be written with either 'joinE' or '($=)': -- -- > import Data.Text as T -- > import Data.Enumerator.List as EL -- > import Data.Enumerator.Text as ET -- > -- > enumFileCounts path = joinE (enumFile path) (EL.map T.length) -- > enumFileCounts path = enumFile path $= EL.map T.length -- -- Since: 0.4.9 ($=) :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b ($=) = joinE -- | Feeds outer input elements into the provided iteratee until it yields -- an inner input, passes that to the inner iteratee, and then loops. sequence :: Monad m => Iteratee ao m ai -> Enumeratee ao ai m b sequence i = loop where loop = checkDone check check k = isEOF >>= \f -> if f then yield (Continue k) EOF else step k step k = i >>= \v -> k (Chunks [v]) >>== loop -- | Sends 'EOF' to its iteratee. Most clients should use 'run' or 'run_' -- instead. enumEOF :: Monad m => Enumerator a m b enumEOF (Yield x _) = yield x EOF enumEOF (Error err) = throwError err enumEOF (Continue k) = k EOF >>== check where check (Continue _) = error "enumEOF: divergent iteratee" check s = enumEOF s -- | A common pattern in 'Enumeratee' implementations is to check whether -- the inner 'Iteratee' has finished, and if so, to return its output. -- 'checkDone' passes its parameter a continuation if the 'Iteratee' -- can still consume input, or yields otherwise. -- -- Since: 0.4.3 checkDoneEx :: Monad m => Stream a' -> ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b checkDoneEx _ f (Continue k) = f k checkDoneEx extra _ step = yield step extra -- | @'checkDone' = 'checkDoneEx' ('Chunks' [])@ -- -- Use this for enumeratees which do not have an input buffer. checkDone :: Monad m => ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b checkDone = checkDoneEx (Chunks []) -- | Check whether a stream has reached EOF. Most clients should use -- 'Data.Enumerator.List.head' instead. isEOF :: Monad m => Iteratee a m Bool isEOF = continue $ \s -> case s of EOF -> yield True s _ -> yield False s -- | Try to run an IO computation. If it throws an exception, the exception -- is caught and converted into an {\tt Error}. -- -- Since: 0.4.9 tryIO :: MonadIO m => IO b -> Iteratee a m b tryIO io = Iteratee $ do tried <- liftIO (Exc.try io) return $ case tried of Right b -> Yield b (Chunks []) Left err -> Error err -- | A common pattern in 'Enumerator' implementations is to check whether -- the inner 'Iteratee' has finished, and if so, to return its output. -- 'checkContinue0' passes its parameter a continuation if the 'Iteratee' -- can still consume input; if not, it returns the iteratee's step. -- -- The type signature here is a bit crazy, but it's actually very easy to -- use. Take this code: -- -- > repeat :: Monad m => a -> Enumerator a m b -- > repeat x = loop where -- > loop (Continue k) = k (Chunks [x]) >>== loop -- > loop step = returnI step -- -- And rewrite it without the boilerplate: -- -- > repeat :: Monad m => a -> Enumerator a m b -- > repeat x = checkContinue0 $ \loop k -> k (Chunks [x] >>== loop -- -- Since: 0.4.9 checkContinue0 :: Monad m => (Enumerator a m b -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> Enumerator a m b checkContinue0 inner = loop where loop (Continue k) = inner loop k loop step = returnI step -- | Like 'checkContinue0', but allows each loop step to use a state value: -- -- > iterate :: Monad m => (a -> a) -> a -> Enumerator a m b -- > iterate f = checkContinue1 $ \loop a k -> k (Chunks [a]) >>== loop (f a) -- -- Since: 0.4.9 checkContinue1 :: Monad m => ((s1 -> Enumerator a m b) -> s1 -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> s1 -> Enumerator a m b checkContinue1 inner = loop where loop s (Continue k) = inner loop s k loop _ step = returnI step -- | Lift an 'Iteratee' onto a monad transformer, re-wrapping the -- 'Iteratee'’s inner monadic values. -- -- Since: 0.1.1 liftTrans :: (Monad m, MonadTrans t, Monad (t m)) => Iteratee a m b -> Iteratee a (t m) b liftTrans iter = Iteratee $ do step <- lift (runIteratee iter) return $ case step of Yield x cs -> Yield x cs Error err -> Error err Continue k -> Continue (liftTrans . k) {-# DEPRECATED liftI "Use 'Data.Enumerator.continue' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.continue' instead liftI :: Monad m => (Stream a -> Step a m b) -> Iteratee a m b liftI k = continue (returnI . k) -- | Peek at the next element in the stream, or 'Nothing' if the stream -- has ended. peek :: Monad m => Iteratee a m (Maybe a) peek = continue loop where loop (Chunks []) = continue loop loop chunk@(Chunks (x:_)) = yield (Just x) chunk loop EOF = yield Nothing EOF -- | Get the last element in the stream, or 'Nothing' if the stream -- has ended. -- -- Consumes the entire stream. last :: Monad m => Iteratee a m (Maybe a) last = continue (loop Nothing) where loop ret (Chunks xs) = continue . loop $ case xs of [] -> ret _ -> Just (Prelude.last xs) loop ret EOF = yield ret EOF -- | Get how many elements remained in the stream. -- -- Consumes the entire stream. length :: Monad m => Iteratee a m Integer length = continue (loop 0) where len = genericLength loop n (Chunks xs) = continue (loop (n + len xs)) loop n EOF = yield n EOF {-# DEPRECATED head "Use 'Data.Enumerator.List.head' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.head' instead head :: Monad m => Iteratee a m (Maybe a) head = EL.head {-# DEPRECATED drop "Use 'Data.Enumerator.List.drop' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.drop' instead drop :: Monad m => Integer -> Iteratee a m () drop = EL.drop {-# DEPRECATED dropWhile "Use 'Data.Enumerator.List.dropWhile' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.dropWhile' instead dropWhile :: Monad m => (a -> Bool) -> Iteratee a m () dropWhile = EL.dropWhile {-# DEPRECATED span "Use 'Data.Enumerator.List.takeWhile' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.takeWhile' instead span :: Monad m => (a -> Bool) -> Iteratee a m [a] span = EL.takeWhile {-# DEPRECATED break "Use 'Data.Enumerator.List.takeWhile' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.takeWhile' instead break :: Monad m => (a -> Bool) -> Iteratee a m [a] break p = EL.takeWhile (not . p) {-# DEPRECATED consume "Use 'Data.Enumerator.List.consume' instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.consume' instead consume :: Monad m => Iteratee a m [a] consume = EL.consume {-# DEPRECATED foldl "Use Data.Enumerator.List.fold instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.fold' instead -- -- Since: 0.4.5 foldl :: Monad m => (b -> a -> b) -> b -> Iteratee a m b foldl step = continue . loop where fold = Prelude.foldl step loop acc stream = case stream of Chunks [] -> continue (loop acc) Chunks xs -> continue (loop (fold acc xs)) EOF -> yield acc EOF {-# DEPRECATED foldl' "Use Data.Enumerator.List.fold instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.fold' instead -- -- Since: 0.4.5 foldl' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b foldl' = EL.fold {-# DEPRECATED foldM "Use Data.Enumerator.List.foldM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.foldM' instead -- -- Since: 0.4.5 foldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b foldM = EL.foldM {-# DEPRECATED iterate "Use Data.Enumerator.List.iterate instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.iterate' instead -- -- Since: 0.4.5 iterate :: Monad m => (a -> a) -> a -> Enumerator a m b iterate = EL.iterate {-# DEPRECATED iterateM "Use Data.Enumerator.List.iterateM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.iterateM' instead -- -- Since: 0.4.5 iterateM :: Monad m => (a -> m a) -> a -> Enumerator a m b iterateM = EL.iterateM {-# DEPRECATED repeat "Use Data.Enumerator.List.repeat instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.repeat' instead -- -- Since: 0.4.5 repeat :: Monad m => a -> Enumerator a m b repeat = EL.repeat {-# DEPRECATED repeatM "Use Data.Enumerator.List.repeatM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.repeatM' instead -- -- Since: 0.4.5 repeatM :: Monad m => m a -> Enumerator a m b repeatM = EL.repeatM {-# DEPRECATED replicate "Use Data.Enumerator.List.replicate instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.replicate' instead -- -- Since: 0.4.5 replicate :: Monad m => Integer -> a -> Enumerator a m b replicate = EL.replicate {-# DEPRECATED replicateM "Use Data.Enumerator.List.replicateM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.replicateM' instead -- -- Since: 0.4.5 replicateM :: Monad m => Integer -> m a -> Enumerator a m b replicateM = EL.replicateM {-# DEPRECATED generateM "Use Data.Enumerator.List.generateM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.generateM' instead -- -- Since: 0.4.5 generateM :: Monad m => m (Maybe a) -> Enumerator a m b generateM = EL.generateM {-# DEPRECATED map "Use Data.Enumerator.List.map instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.map' instead map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b map = EL.map {-# DEPRECATED mapM "Use Data.Enumerator.List.mapM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.mapM' instead -- -- Since: 0.4.3 mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b mapM = EL.mapM {-# DEPRECATED concatMap "Use Data.Enumerator.List.concatMap instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.concatMap' instead -- -- Since: 0.4.3 concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b concatMap = EL.concatMap {-# DEPRECATED concatMapM "Use Data.Enumerator.List.concatMapM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.concatMapM' instead -- -- Since: 0.4.5 concatMapM :: Monad m => (ao -> m [ai]) -> Enumeratee ao ai m b concatMapM = EL.concatMapM {-# DEPRECATED filter "Use Data.Enumerator.List.filter instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.filter' instead -- -- Since: 0.4.5 filter :: Monad m => (a -> Bool) -> Enumeratee a a m b filter = EL.filter {-# DEPRECATED filterM "Use Data.Enumerator.List.filterM instead" #-} -- | Deprecated in 0.4.8: use 'Data.Enumerator.List.filterM' instead -- -- Since: 0.4.5 filterM :: Monad m => (a -> m Bool) -> Enumeratee a a m b filterM = EL.filterM {-# DEPRECATED liftFoldL "Use Data.Enumerator.List.fold instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.fold' instead -- -- Since: 0.1.1 liftFoldL :: Monad m => (b -> a -> b) -> b -> Iteratee a m b liftFoldL = Data.Enumerator.foldl {-# DEPRECATED liftFoldL' "Use Data.Enumerator.List.fold instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.fold' instead -- -- Since: 0.1.1 liftFoldL' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b liftFoldL' = EL.fold {-# DEPRECATED liftFoldM "Use Data.Enumerator.List.foldM instead" #-} -- | Deprecated in 0.4.5: use 'Data.Enumerator.List.foldM' instead -- -- Since: 0.1.1 liftFoldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b liftFoldM = EL.foldM