packages feed

enumerator 0.4.8 → 0.4.9

raw patch · 13 files changed

+741/−244 lines, 13 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Enumerator: ($=) :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b
+ Data.Enumerator: (=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b
+ Data.Enumerator: checkContinue0 :: Monad m => (Enumerator a m b -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> Enumerator a m b
+ Data.Enumerator: checkContinue1 :: Monad m => ((s1 -> Enumerator a m b) -> s1 -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> s1 -> Enumerator a m b
+ Data.Enumerator: tryIO :: MonadIO m => IO b -> Iteratee a m b
+ Data.Enumerator.Binary: mapAccum :: Monad m => (s -> Word8 -> (s, Word8)) -> s -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.Binary: mapAccumM :: Monad m => (s -> Word8 -> m (s, Word8)) -> s -> Enumeratee ByteString ByteString m b
+ Data.Enumerator.List: mapAccum :: Monad m => (s -> ao -> (s, ai)) -> s -> Enumeratee ao ai m b
+ Data.Enumerator.List: mapAccumM :: Monad m => (s -> ao -> m (s, ai)) -> s -> Enumeratee ao ai m b
+ Data.Enumerator.Text: mapAccum :: Monad m => (s -> Char -> (s, Char)) -> s -> Enumeratee Text Text m b
+ Data.Enumerator.Text: mapAccumM :: Monad m => (s -> Char -> m (s, Char)) -> s -> Enumeratee Text Text m b

Files

enumerator.cabal view
@@ -1,5 +1,5 @@ name: enumerator-version: 0.4.8+version: 0.4.9 synopsis: Reliable, high-performance processing with left-fold enumerators license: MIT license-file: license.txt
hs/Data/Enumerator.hs view
@@ -39,6 +39,8 @@ 	, ($$) 	, (>==>) 	, (<==<)+	, (=$)+	, ($=) 	 	-- ** Running iteratees 	, run@@ -54,9 +56,12 @@ 	, joinE 	, Data.Enumerator.sequence 	, enumEOF+	, checkContinue0+	, checkContinue1 	, checkDoneEx 	, checkDone 	, isEOF+	, tryIO 	 	-- ** Testing and debugging 	, printChunks@@ -451,7 +456,36 @@ 	check (Yield x _) = return x 	check (Error e) = throwError e +infixr 0 =$ ++-- | @enum =$ iter = 'joinI' (enum $$ iter)+--+-- &#x201c;Wraps&#x201d; an iteratee /inner/ in an enumeratee /wrapper/.+-- The resulting iteratee will consume /wrapper/&#x2019;s input type and+-- yield /inner/&#x2019;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@@ -465,7 +499,37 @@ 		Yield x _ -> return x 		Continue _ -> error "joinE: divergent iteratee" +infixr 0 $= ++-- | @enum $= enee = 'joinE' enum enee@+--+-- &#x201c;Wraps&#x201d; an enumerator /inner/ in an enumeratee /wrapper/.+-- The resulting enumerator will generate /wrapper/&#x2019;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. @@ -522,6 +586,68 @@ 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   
hs/Data/Enumerator/Binary.hs view
@@ -40,6 +40,10 @@ 	, Data.Enumerator.Binary.concatMap 	, concatMapM 	+	-- ** Accumulating maps+	, mapAccum+	, mapAccumM+	 	-- ** Infinite streams 	, Data.Enumerator.Binary.iterate 	, iterateM@@ -77,11 +81,9 @@ import Data.Enumerator hiding ( head, drop, iterateM, repeatM, replicateM                               , generateM, filterM, consume, foldM                               , concatMapM)-import Data.Enumerator.Util (tryIO) import Control.Monad.IO.Class (MonadIO) import qualified Data.ByteString as B import qualified System.IO as IO-import Data.Function (fix) import qualified Control.Exception as Exc import System.IO.Error (isEOFError) import Data.Word (Word8)@@ -121,11 +123,9 @@ -- Since: 0.4.8  unfold :: Monad m => (s -> Maybe (Word8, s)) -> s -> Enumerator B.ByteString m b-unfold f = loop where-	loop s (Continue k) = case f s of-		Nothing -> continue k-		Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s'-	loop _ step = returnI step+unfold f = checkContinue1 $ \loop s k -> case f s of+	Nothing -> continue k+	Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s'   -- | Enumerates a stream of bytes by repeatedly applying a computation to@@ -136,13 +136,11 @@ -- Since: 0.4.8  unfoldM :: Monad m => (s -> m (Maybe (Word8, s))) -> s -> Enumerator B.ByteString m b-unfoldM f = loop where-	loop s (Continue k) = do-		fs <- lift (f s)-		case fs of-			Nothing -> continue k-			Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s'-	loop _ step = returnI step+unfoldM f = checkContinue1 $ \loop s k -> do+	fs <- lift (f s)+	case fs of+		Nothing -> continue k+		Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s'   -- | @'map' f@ applies /f/ to each input byte and feeds the@@ -189,6 +187,41 @@ 			checkDoneEx (Chunks [B.pack xs]) (\k' -> loop k' xs)  +-- | Similar to 'map', but with a stateful step function.+--+-- Since: 0.4.9++mapAccum :: Monad m => (s -> Word8 -> (s, Word8)) -> s -> Enumeratee B.ByteString B.ByteString m b+mapAccum f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case B.uncons x of+		Nothing -> loop s k xs+		Just (b, x') -> case f s b of+			(s', ai) -> k (Chunks [B.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))+++-- | Similar to 'mapM', but with a stateful step function.+--+-- Since: 0.4.9++mapAccumM :: Monad m => (s -> Word8 -> m (s, Word8)) -> s -> Enumeratee B.ByteString B.ByteString m b+mapAccumM f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case B.uncons x of+		Nothing -> loop s k xs+		Just (b, x') -> do+			(s', ai) <- lift (f s b)+			k (Chunks [B.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))++ -- | @'iterate' f x@ enumerates an infinite stream of repeated applications -- of /f/ to /x/. --@@ -197,9 +230,7 @@ -- Since: 0.4.8  iterate :: Monad m => (Word8 -> Word8) -> Word8 -> Enumerator B.ByteString m b-iterate f = loop where-	loop byte (Continue k) = k (Chunks [B.singleton byte]) >>== loop (f byte)-	loop _ step = returnI step+iterate f = checkContinue1 $ \loop s k -> k (Chunks [B.singleton s]) >>== loop (f s)   -- | Similar to 'iterate', except the iteration function is monadic.@@ -207,11 +238,10 @@ -- Since: 0.4.8  iterateM :: Monad m => (Word8 -> m Word8) -> Word8 -> Enumerator B.ByteString m b-iterateM f base = loop (return base) where-	loop m_byte (Continue k) = do+iterateM f base = worker (return base) where+	worker = checkContinue1 $ \loop m_byte k -> do 		byte <- lift m_byte 		k (Chunks [B.singleton byte]) >>== loop (f byte)-	loop _ step = returnI step   -- | Enumerates an infinite stream of a single byte.@@ -449,16 +479,13 @@            => Integer -- ^ Buffer size            -> IO.Handle            -> Enumerator B.ByteString m b-enumHandle bufferSize h = do+enumHandle bufferSize h = checkContinue0 $ \loop k -> do 	let intSize = fromInteger bufferSize 	-	fix $ \loop step -> case step of-		Continue k -> do-			bytes <- tryIO (getBytes h intSize)-			if B.null bytes-				then continue k-				else k (Chunks [bytes]) >>== loop-		_ -> returnI step+	bytes <- tryIO (getBytes h intSize)+	if B.null bytes+		then continue k+		else k (Chunks [bytes]) >>== loop   -- | Read bytes (in chunks of the given buffer size) from the handle, and@@ -494,19 +521,20 @@ 		Just off -> tryIO (IO.hSeek h IO.AbsoluteSeek off) 	 	enum = case count of-		Just n -> loop n s+		Just n -> enumRange n s 		Nothing -> enumHandle bufferSize h s 	-	loop n (Continue k) =-		let rem = fromInteger (min bufferSize n) in-		if rem <= 0+	enumRange = checkContinue1 $ \loop n k -> let+		rem = fromInteger (min bufferSize n)+		keepGoing = do+			bytes <- tryIO (getBytes h rem)+			if B.null bytes+				then continue k+				else feed bytes+		feed bs = k (Chunks [bs]) >>== loop (n - (toInteger (B.length bs)))+		in if rem <= 0 			then continue k-			else do-				bytes <- tryIO (getBytes h rem)-				if B.null bytes-					then continue k-					else k (Chunks [bytes]) >>== loop (n - (toInteger (B.length bytes)))-	loop _ step = returnI step+			else keepGoing  getBytes :: IO.Handle -> Int -> IO B.ByteString getBytes h n = do
hs/Data/Enumerator/List.hs view
@@ -33,6 +33,10 @@ 	, Data.Enumerator.List.concatMap 	, concatMapM 	+	-- ** Accumulating maps+	, mapAccum+	, mapAccumM+	 	-- ** Infinite streams 	, Data.Enumerator.List.iterate 	, iterateM@@ -114,11 +118,9 @@ -- Since: 0.4.8  unfold :: Monad m => (s -> Maybe (a, s)) -> s -> Enumerator a m b-unfold f = loop where-	loop s (Continue k) = case f s of-		Nothing -> continue k-		Just (a, s') -> k (Chunks [a]) >>== loop s'-	loop _ step = returnI step+unfold f = checkContinue1 $ \loop s k -> case f s of+	Nothing -> continue k+	Just (a, s') -> k (Chunks [a]) >>== loop s'   -- | Enumerates a stream of elements by repeatedly applying a computation to@@ -129,13 +131,11 @@ -- Since: 0.4.8  unfoldM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Enumerator a m b-unfoldM f = loop where-	loop s (Continue k) = do-		fs <- lift (f s)-		case fs of-			Nothing -> continue k-			Just (a, s') -> k (Chunks [a]) >>== loop s'-	loop _ step = returnI step+unfoldM f = checkContinue1 $ \loop s k -> do+	fs <- lift (f s)+	case fs of+		Nothing -> continue k+		Just (a, s') -> k (Chunks [a]) >>== loop s'   -- | @'concatMapM' f@ applies /f/ to each input element and feeds the@@ -186,6 +186,37 @@ mapM f = concatMapM (\x -> Prelude.mapM f [x])  +-- | Similar to 'map', but with a stateful step function.+--+-- Since: 0.4.9++mapAccum :: Monad m => (s -> ao -> (s, ai)) -> s -> Enumeratee ao ai m b+mapAccum f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case f s x of+		(s', ai) -> k (Chunks [ai]) >>==+			checkDoneEx (Chunks xs) (\k' -> loop s' k' xs)+++-- | Similar to 'mapM', but with a stateful step function.+--+-- Since: 0.4.9++mapAccumM :: Monad m => (s -> ao -> m (s, ai)) -> s -> Enumeratee ao ai m b+mapAccumM f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = do+		(s', ai) <- lift (f s x)+		k (Chunks [ai]) >>==+			checkDoneEx (Chunks xs) (\k' -> loop s' k' xs)++ -- | @'iterate' f x@ enumerates an infinite stream of repeated applications -- of /f/ to /x/. --@@ -194,9 +225,7 @@ -- Since: 0.4.8  iterate :: Monad m => (a -> a) -> a -> Enumerator a m b-iterate f = loop where-	loop a (Continue k) = k (Chunks [a]) >>== loop (f a)-	loop _ step = returnI step+iterate f = checkContinue1 $ \loop s k -> k (Chunks [s]) >>== loop (f s)   -- | Similar to 'iterate', except the iteration function is monadic.@@ -205,11 +234,10 @@  iterateM :: Monad m => (a -> m a) -> a          -> Enumerator a m b-iterateM f base = loop (return base) where-	loop m_a (Continue k) = do+iterateM f base = worker (return base) where+	worker = checkContinue1 $ \loop m_a k -> do 		a <- lift m_a 		k (Chunks [a]) >>== loop (f a)-	loop _ step = returnI step   -- | Enumerates an infinite stream of a single element.@@ -219,7 +247,7 @@ -- Since: 0.4.8  repeat :: Monad m => a -> Enumerator a m b-repeat a = Data.Enumerator.List.iterate (const a) a+repeat a = checkContinue0 $ \loop k -> k (Chunks [a]) >>== loop   -- | Enumerates an infinite stream of element. Each element is computed by@@ -266,13 +294,11 @@  generateM :: Monad m => m (Maybe a)           -> Enumerator a m b-generateM getNext = loop where-	loop (Continue k) = do-		next <- lift getNext-		case next of-			Nothing -> continue k-			Just x -> k (Chunks [x]) >>== loop-	loop step = returnI step+generateM getNext = checkContinue0 $ \loop k -> do+	next <- lift getNext+	case next of+		Nothing -> continue k+		Just x -> k (Chunks [x]) >>== loop   -- | Applies a predicate to the stream. The inner iteratee only receives
hs/Data/Enumerator/Text.hs view
@@ -38,6 +38,10 @@ 	, Data.Enumerator.Text.concatMap 	, concatMapM 	+	-- ** Accumulating maps+	, mapAccum+	, mapAccumM+	 	-- ** Infinite streams 	, Data.Enumerator.Text.iterate 	, iterateM@@ -88,7 +92,7 @@ import Data.Enumerator hiding ( head, drop, generateM, filterM, consume                               , concatMapM, iterateM, repeatM, replicateM                               , foldM)-import Data.Enumerator.Util (tryIO, tSpanBy, tlSpanBy, reprWord, reprChar, textToStrict)+import Data.Enumerator.Util (tSpanBy, tlSpanBy, reprWord, reprChar, textToStrict) import Control.Monad.IO.Class (MonadIO) import qualified Control.Exception as Exc import Control.Arrow (first)@@ -140,11 +144,9 @@ -- Since: 0.4.8  unfold :: Monad m => (s -> Maybe (Char, s)) -> s -> Enumerator T.Text m b-unfold f = loop where-	loop s (Continue k) = case f s of-		Nothing -> continue k-		Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s'-	loop _ step = returnI step+unfold f = checkContinue1 $ \loop s k -> case f s of+	Nothing -> continue k+	Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s'   -- | Enumerates a stream of characters by repeatedly applying a computation@@ -155,13 +157,11 @@ -- Since: 0.4.8  unfoldM :: Monad m => (s -> m (Maybe (Char, s))) -> s -> Enumerator T.Text m b-unfoldM f = loop where-	loop s (Continue k) = do-		fs <- lift (f s)-		case fs of-			Nothing -> continue k-			Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s'-	loop _ step = returnI step+unfoldM f = checkContinue1 $ \loop s k -> do+	fs <- lift (f s)+	case fs of+		Nothing -> continue k+		Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s'   -- | @'map' f@ applies /f/ to each input character and feeds the@@ -208,6 +208,41 @@ 			checkDoneEx (Chunks [T.pack xs]) (\k' -> loop k' xs)  +-- | Similar to 'map', but with a stateful step function.+--+-- Since: 0.4.9++mapAccum :: Monad m => (s -> Char -> (s, Char)) -> s -> Enumeratee T.Text T.Text m b+mapAccum f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case T.uncons x of+		Nothing -> loop s k xs+		Just (c, x') -> case f s c of+			(s', ai) -> k (Chunks [T.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))+++-- | Similar to 'mapM', but with a stateful step function.+--+-- Since: 0.4.9++mapAccumM :: Monad m => (s -> Char -> m (s, Char)) -> s -> Enumeratee T.Text T.Text m b+mapAccumM f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case T.uncons x of+		Nothing -> loop s k xs+		Just (c, x') -> do+			(s', ai) <- lift (f s c)+			k (Chunks [T.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))++ -- | @'iterate' f x@ enumerates an infinite stream of repeated applications -- of /f/ to /x/. --@@ -216,9 +251,7 @@ -- Since: 0.4.8  iterate :: Monad m => (Char -> Char) -> Char -> Enumerator T.Text m b-iterate f = loop where-	loop char (Continue k) = k (Chunks [T.singleton char]) >>== loop (f char)-	loop _ step = returnI step+iterate f = checkContinue1 $ \loop s k -> k (Chunks [T.singleton s]) >>== loop (f s)   -- | Similar to 'iterate', except the iteration function is monadic.@@ -226,11 +259,10 @@ -- Since: 0.4.8  iterateM :: Monad m => (Char -> m Char) -> Char -> Enumerator T.Text m b-iterateM f base = loop (return base) where-	loop m_char (Continue k) = do+iterateM f base = worker (return base) where+	worker = checkContinue1 $ \loop m_char k -> do 		char <- lift m_char 		k (Chunks [T.singleton char]) >>== loop (f char)-	loop _ step = returnI step   -- | Enumerates an infinite stream of a single character.@@ -469,19 +501,18 @@  enumHandle :: MonadIO m => IO.Handle            -> Enumerator T.Text m b-enumHandle h = loop where-	loop (Continue k) = do-		maybeText <- tryIO getText-		case maybeText of-			Nothing -> continue k-			Just text -> k (Chunks [text]) >>== loop-	-	loop step = returnI step-	getText = Exc.catch+enumHandle h = checkContinue0 $ \loop k -> do+	let getText = Exc.catch 		(Just `fmap` TIO.hGetLine h) 		(\err -> if isEOFError err 			then return Nothing 			else Exc.throwIO err)+	+	maybeText <- tryIO getText+	case maybeText of+		Nothing -> continue k+		Just text -> k (Chunks [text]) >>== loop+	   -- | Opens a file path in text mode, and passes the handle to 'enumHandle'.
hs/Data/Enumerator/Util.hs view
@@ -1,23 +1,12 @@  {-# LANGUAGE CPP #-} module Data.Enumerator.Util where-import Data.Enumerator  import Data.Char (toUpper, intToDigit, ord) import Data.Word (Word8) import qualified Data.Text as T import qualified Data.Text.Lazy as TL--import Control.Monad.IO.Class (MonadIO, liftIO)-import qualified Control.Exception as Exc import Numeric (showIntAtBase)--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  pad0 :: Int -> String -> String pad0 size str = padded where
src/api-docs.anansi view
@@ -111,6 +111,54 @@ -- Since: 0.1.1 : +:d apidoc Data.Enumerator.($=)+-- | @enum $= enee = 'joinE' enum enee@+--+-- &#x201c;Wraps&#x201d; an enumerator /inner/ in an enumeratee /wrapper/.+-- The resulting enumerator will generate /wrapper/&#x2019;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+:++:d apidoc Data.Enumerator.(=$)+-- | @enum =$ iter = 'joinI' (enum $$ iter)+--+-- &#x201c;Wraps&#x201d; an iteratee /inner/ in an enumeratee /wrapper/.+-- The resulting iteratee will consume /wrapper/&#x2019;s input type and+-- yield /inner/&#x2019;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+:+ :d apidoc Data.Enumerator.(<==<) -- | @'(\<==\<)' = flip '(>==>)'@ --@@ -199,6 +247,37 @@ -- Since: 0.1.1 : +:d apidoc Data.Enumerator.checkContinue0+-- | 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+:++:d apidoc Data.Enumerator.checkContinue1+-- | 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+:+ :d apidoc Data.Enumerator.checkDone -- | @'checkDone' = 'checkDoneEx' ('Chunks' [])@ --@@ -628,6 +707,18 @@ -- Since: 0.4.8 : +:d apidoc Data.Enumerator.Binary.mapAccum+-- | Similar to 'map', but with a stateful step function.+--+-- Since: 0.4.9+:++:d apidoc Data.Enumerator.Binary.mapAccumM+-- | Similar to 'mapM', but with a stateful step function.+--+-- Since: 0.4.9+:+ :d apidoc Data.Enumerator.Binary.repeat -- | Enumerates an infinite stream of a single byte. --@@ -824,6 +915,18 @@ -- Since: 0.4.8 : +:d apidoc Data.Enumerator.List.mapAccum+-- | Similar to 'map', but with a stateful step function.+--+-- Since: 0.4.9+:++:d apidoc Data.Enumerator.List.mapAccumM+-- | Similar to 'mapM', but with a stateful step function.+--+-- Since: 0.4.9+:+ :d apidoc Data.Enumerator.List.repeat -- | Enumerates an infinite stream of a single element. --@@ -1063,6 +1166,18 @@ -- Since: 0.4.8 : +:d apidoc Data.Enumerator.Text.mapAccum+-- | Similar to 'map', but with a stateful step function.+--+-- Since: 0.4.9+:++:d apidoc Data.Enumerator.Text.mapAccumM+-- | Similar to 'mapM', but with a stateful step function.+--+-- Since: 0.4.9+:+ :d apidoc Data.Enumerator.Text.repeat -- | Enumerates an infinite stream of a single character. --@@ -1134,4 +1249,11 @@ -- Similar to 'iterateM'. -- -- Since: 0.4.8+:++:d apidoc Data.Enumerator.tryIO+-- | 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 :
src/enumerator.anansi view
@@ -30,10 +30,10 @@  \newcommand{\io}{{\sc i/o}} -\title{enumerator\_0.4.8}+\title{enumerator\_0.4.9} \author{John Millikin\\         \href{mailto:"John Millikin" <jmillikin@gmail.com>}{\tt jmillikin@gmail.com}}-\date{March 19, 2011}+\date{March 29, 2011}  \begin{document} 
src/io.anansi view
@@ -15,16 +15,13 @@            => Integer -- ^ Buffer size            -> IO.Handle            -> Enumerator B.ByteString m b-enumHandle bufferSize h = do+enumHandle bufferSize h = checkContinue0 $ \loop k -> do 	let intSize = fromInteger bufferSize 	-	fix $ \loop step -> case step of-		Continue k -> do-			bytes <- tryIO (getBytes h intSize)-			if B.null bytes-				then continue k-				else k (Chunks [bytes]) >>== loop-		_ -> returnI step+	bytes <- tryIO (getBytes h intSize)+	if B.null bytes+		then continue k+		else k (Chunks [bytes]) >>== loop :  :d binary IO@@ -41,19 +38,20 @@ 		Just off -> tryIO (IO.hSeek h IO.AbsoluteSeek off) 	 	enum = case count of-		Just n -> loop n s+		Just n -> enumRange n s 		Nothing -> enumHandle bufferSize h s 	-	loop n (Continue k) =-		let rem = fromInteger (min bufferSize n) in-		if rem <= 0+	enumRange = checkContinue1 $ \loop n k -> let+		rem = fromInteger (min bufferSize n)+		keepGoing = do+			bytes <- tryIO (getBytes h rem)+			if B.null bytes+				then continue k+				else feed bytes+		feed bs = k (Chunks [bs]) >>== loop (n - (toInteger (B.length bs)))+		in if rem <= 0 			then continue k-			else do-				bytes <- tryIO (getBytes h rem)-				if B.null bytes-					then continue k-					else k (Chunks [bytes]) >>== loop (n - (toInteger (B.length bytes)))-	loop _ step = returnI step+			else keepGoing :  :d binary IO@@ -110,19 +108,18 @@ |apidoc Data.Enumerator.Text.enumHandle| enumHandle :: MonadIO m => IO.Handle            -> Enumerator T.Text m b-enumHandle h = loop where-	loop (Continue k) = do-		maybeText <- tryIO getText-		case maybeText of-			Nothing -> continue k-			Just text -> k (Chunks [text]) >>== loop-	-	loop step = returnI step-	getText = Exc.catch+enumHandle h = checkContinue0 $ \loop k -> do+	let getText = Exc.catch 		(Just `fmap` TIO.hGetLine h) 		(\err -> if isEOFError err 			then return Nothing 			else Exc.throwIO err)+	+	maybeText <- tryIO getText+	case maybeText of+		Nothing -> continue k+		Just text -> k (Chunks [text]) >>== loop+	 :  :d text IO
src/list-analogues.anansi view
@@ -65,67 +65,55 @@ :d element-oriented list analogues |apidoc Data.Enumerator.List.unfold| unfold :: Monad m => (s -> Maybe (a, s)) -> s -> Enumerator a m b-unfold f = loop where-	loop s (Continue k) = case f s of-		Nothing -> continue k-		Just (a, s') -> k (Chunks [a]) >>== loop s'-	loop _ step = returnI step+unfold f = checkContinue1 $ \loop s k -> case f s of+	Nothing -> continue k+	Just (a, s') -> k (Chunks [a]) >>== loop s' :  :d byte-oriented list analogues |apidoc Data.Enumerator.Binary.unfold| unfold :: Monad m => (s -> Maybe (Word8, s)) -> s -> Enumerator B.ByteString m b-unfold f = loop where-	loop s (Continue k) = case f s of-		Nothing -> continue k-		Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s'-	loop _ step = returnI step+unfold f = checkContinue1 $ \loop s k -> case f s of+	Nothing -> continue k+	Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s' :  :d text-oriented list analogues |apidoc Data.Enumerator.Text.unfold| unfold :: Monad m => (s -> Maybe (Char, s)) -> s -> Enumerator T.Text m b-unfold f = loop where-	loop s (Continue k) = case f s of-		Nothing -> continue k-		Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s'-	loop _ step = returnI step+unfold f = checkContinue1 $ \loop s k -> case f s of+	Nothing -> continue k+	Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s' :  :d element-oriented list analogues |apidoc Data.Enumerator.List.unfoldM| unfoldM :: Monad m => (s -> m (Maybe (a, s))) -> s -> Enumerator a m b-unfoldM f = loop where-	loop s (Continue k) = do-		fs <- lift (f s)-		case fs of-			Nothing -> continue k-			Just (a, s') -> k (Chunks [a]) >>== loop s'-	loop _ step = returnI step+unfoldM f = checkContinue1 $ \loop s k -> do+	fs <- lift (f s)+	case fs of+		Nothing -> continue k+		Just (a, s') -> k (Chunks [a]) >>== loop s' :  :d byte-oriented list analogues |apidoc Data.Enumerator.Binary.unfoldM| unfoldM :: Monad m => (s -> m (Maybe (Word8, s))) -> s -> Enumerator B.ByteString m b-unfoldM f = loop where-	loop s (Continue k) = do-		fs <- lift (f s)-		case fs of-			Nothing -> continue k-			Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s'-	loop _ step = returnI step+unfoldM f = checkContinue1 $ \loop s k -> do+	fs <- lift (f s)+	case fs of+		Nothing -> continue k+		Just (b, s') -> k (Chunks [B.singleton b]) >>== loop s' :  :d text-oriented list analogues |apidoc Data.Enumerator.Text.unfoldM| unfoldM :: Monad m => (s -> m (Maybe (Char, s))) -> s -> Enumerator T.Text m b-unfoldM f = loop where-	loop s (Continue k) = do-		fs <- lift (f s)-		case fs of-			Nothing -> continue k-			Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s'-	loop _ step = returnI step+unfoldM f = checkContinue1 $ \loop s k -> do+	fs <- lift (f s)+	case fs of+		Nothing -> continue k+		Just (c, s') -> k (Chunks [T.singleton c]) >>== loop s' :  \subsection{Maps}@@ -226,6 +214,91 @@ 			checkDoneEx (Chunks [T.pack xs]) (\k' -> loop k' xs) : +\subsection{Accumulating maps}++:d element-oriented list analogues+|apidoc Data.Enumerator.List.mapAccum|+mapAccum :: Monad m => (s -> ao -> (s, ai)) -> s -> Enumeratee ao ai m b+mapAccum f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case f s x of+		(s', ai) -> k (Chunks [ai]) >>==+			checkDoneEx (Chunks xs) (\k' -> loop s' k' xs)++|apidoc Data.Enumerator.List.mapAccumM|+mapAccumM :: Monad m => (s -> ao -> m (s, ai)) -> s -> Enumeratee ao ai m b+mapAccumM f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = do+		(s', ai) <- lift (f s x)+		k (Chunks [ai]) >>==+			checkDoneEx (Chunks xs) (\k' -> loop s' k' xs)+:++:d byte-oriented list analogues+|apidoc Data.Enumerator.Binary.mapAccum|+mapAccum :: Monad m => (s -> Word8 -> (s, Word8)) -> s -> Enumeratee B.ByteString B.ByteString m b+mapAccum f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case B.uncons x of+		Nothing -> loop s k xs+		Just (b, x') -> case f s b of+			(s', ai) -> k (Chunks [B.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))++|apidoc Data.Enumerator.Binary.mapAccumM|+mapAccumM :: Monad m => (s -> Word8 -> m (s, Word8)) -> s -> Enumeratee B.ByteString B.ByteString m b+mapAccumM f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case B.uncons x of+		Nothing -> loop s k xs+		Just (b, x') -> do+			(s', ai) <- lift (f s b)+			k (Chunks [B.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))+:++:d text-oriented list analogues+|apidoc Data.Enumerator.Text.mapAccum|+mapAccum :: Monad m => (s -> Char -> (s, Char)) -> s -> Enumeratee T.Text T.Text m b+mapAccum f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case T.uncons x of+		Nothing -> loop s k xs+		Just (c, x') -> case f s c of+			(s', ai) -> k (Chunks [T.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))++|apidoc Data.Enumerator.Text.mapAccumM|+mapAccumM :: Monad m => (s -> Char -> m (s, Char)) -> s -> Enumeratee T.Text T.Text m b+mapAccumM f s0 = checkDone (continue . step s0) where+	step _ k EOF = yield (Continue k) EOF+	step s k (Chunks xs) = loop s k xs+	+	loop s k [] = continue (step s k)+	loop s k (x:xs) = case T.uncons x of+		Nothing -> loop s k xs+		Just (c, x') -> do+			(s', ai) <- lift (f s c)+			k (Chunks [T.singleton ai]) >>==+				checkDoneEx (Chunks (x':xs)) (\k' -> loop s' k' (x':xs))+:+ \subsection{Infinite streams}  {\tt iterate} and {\tt iterateM} apply a function repeatedly to the base@@ -234,56 +307,47 @@ :d element-oriented list analogues |apidoc Data.Enumerator.List.iterate| iterate :: Monad m => (a -> a) -> a -> Enumerator a m b-iterate f = loop where-	loop a (Continue k) = k (Chunks [a]) >>== loop (f a)-	loop _ step = returnI step+iterate f = checkContinue1 $ \loop s k -> k (Chunks [s]) >>== loop (f s) :  :d byte-oriented list analogues |apidoc Data.Enumerator.Binary.iterate| iterate :: Monad m => (Word8 -> Word8) -> Word8 -> Enumerator B.ByteString m b-iterate f = loop where-	loop byte (Continue k) = k (Chunks [B.singleton byte]) >>== loop (f byte)-	loop _ step = returnI step+iterate f = checkContinue1 $ \loop s k -> k (Chunks [B.singleton s]) >>== loop (f s) :  :d text-oriented list analogues |apidoc Data.Enumerator.Text.iterate| iterate :: Monad m => (Char -> Char) -> Char -> Enumerator T.Text m b-iterate f = loop where-	loop char (Continue k) = k (Chunks [T.singleton char]) >>== loop (f char)-	loop _ step = returnI step+iterate f = checkContinue1 $ \loop s k -> k (Chunks [T.singleton s]) >>== loop (f s) :  :d element-oriented list analogues |apidoc Data.Enumerator.List.iterateM| iterateM :: Monad m => (a -> m a) -> a          -> Enumerator a m b-iterateM f base = loop (return base) where-	loop m_a (Continue k) = do+iterateM f base = worker (return base) where+	worker = checkContinue1 $ \loop m_a k -> do 		a <- lift m_a 		k (Chunks [a]) >>== loop (f a)-	loop _ step = returnI step :  :d byte-oriented list analogues |apidoc Data.Enumerator.Binary.iterateM| iterateM :: Monad m => (Word8 -> m Word8) -> Word8 -> Enumerator B.ByteString m b-iterateM f base = loop (return base) where-	loop m_byte (Continue k) = do+iterateM f base = worker (return base) where+	worker = checkContinue1 $ \loop m_byte k -> do 		byte <- lift m_byte 		k (Chunks [B.singleton byte]) >>== loop (f byte)-	loop _ step = returnI step :  :d text-oriented list analogues |apidoc Data.Enumerator.Text.iterateM| iterateM :: Monad m => (Char -> m Char) -> Char -> Enumerator T.Text m b-iterateM f base = loop (return base) where-	loop m_char (Continue k) = do+iterateM f base = worker (return base) where+	worker = checkContinue1 $ \loop m_char k -> do 		char <- lift m_char 		k (Chunks [T.singleton char]) >>== loop (f char)-	loop _ step = returnI step :  {\tt repeat} and {\tt repeatM} create infinite streams, where each input@@ -292,7 +356,7 @@ :d element-oriented list analogues |apidoc Data.Enumerator.List.repeat| repeat :: Monad m => a -> Enumerator a m b-repeat a = Data.Enumerator.List.iterate (const a) a+repeat a = checkContinue0 $ \loop k -> k (Chunks [a]) >>== loop :  :d element-oriented list analogues@@ -378,13 +442,11 @@ |apidoc Data.Enumerator.List.generateM| generateM :: Monad m => m (Maybe a)           -> Enumerator a m b-generateM getNext = loop where-	loop (Continue k) = do-		next <- lift getNext-		case next of-			Nothing -> continue k-			Just x -> k (Chunks [x]) >>== loop-	loop step = returnI step+generateM getNext = checkContinue0 $ \loop k -> do+	next <- lift getNext+	case next of+		Nothing -> continue k+		Just x -> k (Chunks [x]) >>== loop :  :d byte-oriented list analogues
src/public-interface.anansi view
@@ -70,11 +70,9 @@ import Data.Enumerator hiding ( head, drop, iterateM, repeatM, replicateM                               , generateM, filterM, consume, foldM                               , concatMapM)-import Data.Enumerator.Util (tryIO) import Control.Monad.IO.Class (MonadIO) import qualified Data.ByteString as B import qualified System.IO as IO-import Data.Function (fix) import qualified Control.Exception as Exc import System.IO.Error (isEOFError) import Data.Word (Word8)@@ -101,7 +99,7 @@ import Data.Enumerator hiding ( head, drop, generateM, filterM, consume                               , concatMapM, iterateM, repeatM, replicateM                               , foldM)-import Data.Enumerator.Util (tryIO, tSpanBy, tlSpanBy, reprWord, reprChar, textToStrict)+import Data.Enumerator.Util (tSpanBy, tlSpanBy, reprWord, reprChar, textToStrict) import Control.Monad.IO.Class (MonadIO) import qualified Control.Exception as Exc import Control.Arrow (first)@@ -143,6 +141,8 @@ , ($$) , (>==>) , (<==<)+, (=$)+, ($=)  -- ** Running iteratees , run@@ -158,9 +158,12 @@ , joinE , Data.Enumerator.sequence , enumEOF+, checkContinue0+, checkContinue1 , checkDoneEx , checkDone , isEOF+, tryIO  -- ** Testing and debugging , printChunks@@ -223,6 +226,10 @@ , Data.Enumerator.Binary.concatMap , concatMapM +-- ** Accumulating maps+, mapAccum+, mapAccumM+ -- ** Infinite streams , Data.Enumerator.Binary.iterate , iterateM@@ -268,6 +275,10 @@ , Data.Enumerator.List.concatMap , concatMapM +-- ** Accumulating maps+, mapAccum+, mapAccumM+ -- ** Infinite streams , Data.Enumerator.List.iterate , iterateM@@ -316,6 +327,10 @@ , Data.Enumerator.Text.mapM , Data.Enumerator.Text.concatMap , concatMapM++-- ** Accumulating maps+, mapAccum+, mapAccumM  -- ** Infinite streams , Data.Enumerator.Text.iterate
src/utilities.anansi view
@@ -29,6 +29,14 @@ 	check (Error e) = throwError e : +:d unsorted utilities+infixr 0 =$++|apidoc Data.Enumerator.(=$)|+(=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b+enum =$ iter = joinI (enum $$ iter)+:+ {\tt joinE} is similar, except it flattens an enumerator/enumeratee pair into a single enumerator. @@ -46,6 +54,17 @@ 		Continue _ -> error "joinE: divergent iteratee" : +:d unsorted utilities+infixr 0 $=++|apidoc Data.Enumerator.($=)|+($=) :: Monad m+     => Enumerator ao m (Step ai m b)+     -> Enumeratee ao ai m b+     -> Enumerator ai m b+($=) = joinE+:+ {\tt sequence} repeatedly runs its parameter to transform the stream.  :d unsorted utilities@@ -104,31 +123,65 @@ 	_ -> yield False s : +When an enumerator has to interact with the outside world, it usually+catches any exceptions that arise, and propagate them as {\tt Error} steps+instead. {\tt tryIO} encapsulates that pattern.++:d unsorted utilities+|apidoc Data.Enumerator.tryIO|+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+:++Another enumerator pattern that pops up often is a loop that ignores any+non-{\tt Continue} steps. This is especially useful when implementing+most enumerators. It's sort of an analogue to {\tt checkDone}, so I+called it {\tt checkContinue}. It's actually implemented by various+functions ({\tt checkContinue0}, {\tt checkContinue1}, etc), as most+enumerators have some sort of state to pass around.++:d unsorted utilities+|apidoc Data.Enumerator.checkContinue0|+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+:++:d unsorted utilities+|apidoc Data.Enumerator.checkContinue1|+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+:+ {\tt Data.Enumerator.Util} is a hidden module for functions used by several public modules, but not logically part of the {\tt enumerator} API.  :f Data/Enumerator/Util.hs {-# LANGUAGE CPP #-} module Data.Enumerator.Util where-import Data.Enumerator  import Data.Char (toUpper, intToDigit, ord) import Data.Word (Word8) import qualified Data.Text as T import qualified Data.Text.Lazy as TL--import Control.Monad.IO.Class (MonadIO, liftIO)-import qualified Control.Exception as Exc import Numeric (showIntAtBase)-:--:f Data/Enumerator/Util.hs-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 :  :f Data/Enumerator/Util.hs
tests/Properties.hs view
@@ -34,7 +34,6 @@ tests :: [F.Test] tests = 	[ test_StreamInstances-	, test_Primitives 	, test_Text 	, test_ListAnalogues 	, test_Other@@ -132,38 +131,6 @@  -- }}} --- Primitives {{{--test_Primitives :: F.Test-test_Primitives = F.testGroup "Primitives"-	[ test_Map-	, test_ConcatMap-	, test_MapM-	, test_ConcatMapM-	, test_Filter-	, test_FilterM-	]--test_Map :: F.Test-test_Map = test_Enumeratee "map" (EL.map id)--test_ConcatMap :: F.Test-test_ConcatMap = test_Enumeratee "concatMap" (EL.concatMap (:[]))--test_MapM :: F.Test-test_MapM = test_Enumeratee "mapM" (EL.mapM return)--test_ConcatMapM :: F.Test-test_ConcatMapM = test_Enumeratee "concatMapM" (EL.concatMapM (\x -> return [x]))--test_Filter :: F.Test-test_Filter = test_Enumeratee "filter" (EL.filter (\_ -> True))--test_FilterM :: F.Test-test_FilterM = test_Enumeratee "filterM" (EL.filterM (\_ -> return True))---- }}}- -- Text encoding / decoding {{{  test_Text :: F.Test@@ -435,6 +402,14 @@ 	, test_Require 	, test_Isolate 	, test_SplitWhen+	, test_Map+	, test_ConcatMap+	, test_MapM+	, test_ConcatMapM+	, test_MapAccum+	, test_MapAccumM+	, test_Filter+	, test_FilterM 	]  check :: Eq b => E.Iteratee a Identity b -> ([a] -> Either Exc.ErrorCall b) -> [a] -> Bool@@ -616,6 +591,79 @@ 		split = LS.split . LS.dropFinalBlank . LS.dropDelims . LS.whenElt 		words = BL.unpack bytes 		in Right (map B.pack (split (== x) words), []))++test_Map :: F.Test+test_Map = test_Enumeratee "map" (EL.map id)++test_ConcatMap :: F.Test+test_ConcatMap = test_Enumeratee "concatMap" (EL.concatMap (:[]))++test_MapM :: F.Test+test_MapM = test_Enumeratee "mapM" (EL.mapM return)++test_ConcatMapM :: F.Test+test_ConcatMapM = test_Enumeratee "concatMapM" (EL.concatMapM (\x -> return [x]))++test_MapAccum :: F.Test+test_MapAccum = testListAnalogue "mapAccum"+	(do+		let enee = EL.mapAccum (\s ao -> (s+1, (s, ao))) 10+		a <- E.joinI (enee $$ EL.head)+		b <- EL.consume+		return (a, b))+	(\xs -> Right $ case xs of+		[] -> (Nothing, [])+		(x:xs') -> (Just (10, x), xs'))+	(do+		let enee = ET.mapAccum (\s ao -> (s+1, succ ao)) 10+		a <- E.joinI (enee $$ EL.head)+		b <- ET.consume+		return (a, b))+	(\text -> Right $ case TL.uncons text of+		Nothing -> (Nothing, TL.empty)+		Just (c, text') -> (Just (T.singleton (succ c)), text'))+	(do+		let enee = EB.mapAccum (\s ao -> (s+1, ao + s)) 10+		a <- E.joinI (enee $$ EL.head)+		b <- EB.consume+		return (a, b))+	(\bytes -> Right $ case BL.uncons bytes of+		Nothing -> (Nothing, BL.empty)+		Just (b, bytes') -> (Just (B.singleton (b + 10)), bytes'))+++test_MapAccumM :: F.Test+test_MapAccumM = testListAnalogue "mapAccumM"+	(do+		let enee = EL.mapAccumM (\s ao -> return (s+1, (s, ao))) 10+		a <- E.joinI (enee $$ EL.head)+		b <- EL.consume+		return (a, b))+	(\xs -> Right $ case xs of+		[] -> (Nothing, [])+		(x:xs') -> (Just (10, x), xs'))+	(do+		let enee = ET.mapAccumM (\s ao -> return (s+1, succ ao)) 10+		a <- E.joinI (enee $$ EL.head)+		b <- ET.consume+		return (a, b))+	(\text -> Right $ case TL.uncons text of+		Nothing -> (Nothing, TL.empty)+		Just (c, text') -> (Just (T.singleton (succ c)), text'))+	(do+		let enee = EB.mapAccumM (\s ao -> return (s+1, ao + s)) 10+		a <- E.joinI (enee $$ EL.head)+		b <- EB.consume+		return (a, b))+	(\bytes -> Right $ case BL.uncons bytes of+		Nothing -> (Nothing, BL.empty)+		Just (b, bytes') -> (Just (B.singleton (b + 10)), bytes'))++test_Filter :: F.Test+test_Filter = test_Enumeratee "filter" (EL.filter (\_ -> True))++test_FilterM :: F.Test+test_FilterM = test_Enumeratee "filterM" (EL.filterM (\_ -> return True))  -- }}}