Portability | portable |
---|---|
Maintainer | jmillikin@gmail.com |
Data.Enumerator
Contents
Description
Core enumerator types, and some useful primitives.
This module is intended to be imported qualified:
import qualified Data.Enumerator as E
- data Stream a
- newtype Iteratee a m b = Iteratee {
- runIteratee :: m (Step a m b)
- data Step a m b
- type Enumerator a m b = Step a m b -> Iteratee a m b
- type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)
- returnI :: Monad m => Step a m b -> Iteratee a m b
- continue :: Monad m => (Stream a -> Iteratee a m b) -> Iteratee a m b
- yield :: Monad m => b -> Stream a -> Iteratee a m b
- (>>==) :: Monad m => Iteratee a m b -> (Step a m b -> Iteratee a' m b') -> Iteratee a' m b'
- (==<<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b'
- ($$) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b'
- (>==>) :: Monad m => Enumerator a m b -> (Step a m b -> Iteratee a' m b') -> Step a m b -> Iteratee a' m b'
- (<==<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Enumerator a m b -> Step a m b -> Iteratee a' m b'
- (=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b
- ($=) :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b
- run :: Monad m => Iteratee a m b -> m (Either SomeException b)
- run_ :: Monad m => Iteratee a m b -> m b
- throwError :: (Monad m, Exception e) => e -> Iteratee a m b
- catchError :: Monad m => Iteratee a m b -> (SomeException -> Iteratee a m b) -> Iteratee a m b
- concatEnums :: Monad m => [Enumerator a m b] -> Enumerator a m b
- joinI :: Monad m => Iteratee a m (Step a' m b) -> Iteratee a m b
- joinE :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b
- sequence :: Monad m => Iteratee ao m ai -> Enumeratee ao ai m b
- enumEOF :: Monad m => Enumerator a m b
- checkContinue0 :: Monad m => (Enumerator a m b -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> Enumerator a m b
- checkContinue1 :: Monad m => ((s1 -> Enumerator a m b) -> s1 -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> s1 -> Enumerator a m b
- checkDoneEx :: Monad m => Stream a' -> ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
- checkDone :: Monad m => ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
- isEOF :: Monad m => Iteratee a m Bool
- tryIO :: MonadIO m => IO b -> Iteratee a m b
- printChunks :: (MonadIO m, Show a) => Bool -> Iteratee a m ()
- enumList :: Monad m => Integer -> [a] -> Enumerator a m b
- liftTrans :: (Monad m, MonadTrans t, Monad (t m)) => Iteratee a m b -> Iteratee a (t m) b
- liftI :: Monad m => (Stream a -> Step a m b) -> Iteratee a m b
- peek :: Monad m => Iteratee a m (Maybe a)
- last :: Monad m => Iteratee a m (Maybe a)
- length :: Monad m => Iteratee a m Integer
- head :: Monad m => Iteratee a m (Maybe a)
- drop :: Monad m => Integer -> Iteratee a m ()
- dropWhile :: Monad m => (a -> Bool) -> Iteratee a m ()
- span :: Monad m => (a -> Bool) -> Iteratee a m [a]
- break :: Monad m => (a -> Bool) -> Iteratee a m [a]
- consume :: Monad m => Iteratee a m [a]
- foldl :: Monad m => (b -> a -> b) -> b -> Iteratee a m b
- foldl' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b
- foldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b
- iterate :: Monad m => (a -> a) -> a -> Enumerator a m b
- iterateM :: Monad m => (a -> m a) -> a -> Enumerator a m b
- repeat :: Monad m => a -> Enumerator a m b
- repeatM :: Monad m => m a -> Enumerator a m b
- replicate :: Monad m => Integer -> a -> Enumerator a m b
- replicateM :: Monad m => Integer -> m a -> Enumerator a m b
- generateM :: Monad m => m (Maybe a) -> Enumerator a m b
- map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b
- mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b
- concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b
- concatMapM :: Monad m => (ao -> m [ai]) -> Enumeratee ao ai m b
- filter :: Monad m => (a -> Bool) -> Enumeratee a a m b
- filterM :: Monad m => (a -> m Bool) -> Enumeratee a a m b
- liftFoldL :: Monad m => (b -> a -> b) -> b -> Iteratee a m b
- liftFoldL' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b
- liftFoldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b
Types
data Stream a
A Stream
is a sequence of chunks generated by an Enumerator
.
(
is used to indicate that a stream is still active, but
currently has no available data. Iteratees should ignore empty chunks.
Chunks
[])
newtype Iteratee a m b
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.
Constructors
Iteratee | |
Fields
|
data Step a m b
Constructors
Continue (Stream a -> Iteratee a m b) | The |
Yield b (Stream a) | The |
Error SomeException | The |
type Enumerator a m b = Step a m b -> Iteratee a m b
While Iteratee
s consume data, enumerators generate it. Since
is an alias for Iteratee
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 Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai 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
).
Primitives
yield :: Monad m => b -> Stream a -> Iteratee a m b
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.
Operators
(==<<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b'
'(==<<)' = flip '(>>==)'
($$) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b'
'($$)' = '(==<<)'
This might be easier to read when passing a chain of iteratees to an enumerator.
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
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 '(>==>)'
Since: 0.1.1
(=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b
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 => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b
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
Running iteratees
run :: Monad m => Iteratee a m b -> m (Either SomeException b)
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 b
Like run
, except errors are converted to exceptions and thrown.
Primarily useful for small scripts or other simple cases.
Since: 0.4.1
Error handling
throwError :: (Monad m, Exception e) => e -> Iteratee a m b
throwError
exc =returnI
(Error
(toException
exc))
catchError :: Monad m => Iteratee a m b -> (SomeException -> Iteratee a m b) -> Iteratee a m b
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 SomeException
, libraries with
varying error types can be easily composed.
Since: 0.1.1
Miscellaneous
concatEnums :: Monad m => [Enumerator a m b] -> Enumerator a m b
Compose a list of Enumerator
s using '(>>==)'
joinI :: Monad m => Iteratee a m (Step a' m b) -> Iteratee a m b
joinI
is used to “flatten” Enumeratee
s into an
Iteratee
.
joinE :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b
Flatten an enumerator/enumeratee pair into a single enumerator.
sequence :: Monad m => Iteratee ao m ai -> Enumeratee ao ai m b
Feeds outer input elements into the provided iteratee until it yields an inner input, passes that to the inner iteratee, and then loops.
enumEOF :: Monad m => Enumerator a m b
checkContinue0 :: Monad m => (Enumerator a m b -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> Enumerator a m b
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
checkContinue1 :: Monad m => ((s1 -> Enumerator a m b) -> s1 -> (Stream a -> Iteratee a m b) -> Iteratee a m b) -> s1 -> Enumerator a m b
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
checkDoneEx :: Monad m => Stream a' -> ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
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
checkDone :: Monad m => ((Stream a -> Iteratee a m b) -> Iteratee a' m (Step a m b)) -> Enumeratee a' a m b
checkDone
=checkDoneEx
(Chunks
[])
Use this for enumeratees which do not have an input buffer.
isEOF :: Monad m => Iteratee a m Bool
Check whether a stream has reached EOF. Most clients should use
Data.Enumerator.List.head
instead.
tryIO :: MonadIO m => IO b -> Iteratee a m b
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
Testing and debugging
Print chunks as they're received from the enumerator, optionally printing empty chunks.
enumList :: Monad m => Integer -> [a] -> Enumerator a m b
enumerates xs as a stream, passing n inputs per
chunk.
enumList
n xs
Primarily useful for testing and debugging.
Legacy compatibility
Obsolete
liftI :: Monad m => (Stream a -> Step a m b) -> Iteratee a m b
Deprecated in 0.4.5: use continue
instead
peek :: Monad m => Iteratee a m (Maybe a)
Peek at the next element in the stream, or Nothing
if the stream
has ended.
last :: Monad m => Iteratee a m (Maybe a)
Get the last element in the stream, or Nothing
if the stream
has ended.
Consumes the entire stream.
length :: Monad m => Iteratee a m Integer
Get how many elements remained in the stream.
Consumes the entire stream.
Aliases
drop :: Monad m => Integer -> Iteratee a m ()
Deprecated in 0.4.5: use Data.Enumerator.List.drop
instead
dropWhile :: Monad m => (a -> Bool) -> Iteratee a m ()
Deprecated in 0.4.5: use Data.Enumerator.List.dropWhile
instead
span :: Monad m => (a -> Bool) -> Iteratee a m [a]
Deprecated in 0.4.5: use Data.Enumerator.List.takeWhile
instead
break :: Monad m => (a -> Bool) -> Iteratee a m [a]
Deprecated in 0.4.5: use Data.Enumerator.List.takeWhile
instead
foldl :: Monad m => (b -> a -> b) -> b -> Iteratee a m b
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
Deprecated in 0.4.8: use Data.Enumerator.List.fold
instead
Since: 0.4.5
foldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b
Deprecated in 0.4.8: use Data.Enumerator.List.foldM
instead
Since: 0.4.5
iterate :: Monad m => (a -> a) -> a -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.iterate
instead
Since: 0.4.5
iterateM :: Monad m => (a -> m a) -> a -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.iterateM
instead
Since: 0.4.5
repeat :: Monad m => a -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.repeat
instead
Since: 0.4.5
repeatM :: Monad m => m a -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.repeatM
instead
Since: 0.4.5
replicate :: Monad m => Integer -> a -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.replicate
instead
Since: 0.4.5
replicateM :: Monad m => Integer -> m a -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.replicateM
instead
Since: 0.4.5
generateM :: Monad m => m (Maybe a) -> Enumerator a m b
Deprecated in 0.4.8: use Data.Enumerator.List.generateM
instead
Since: 0.4.5
map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b
Deprecated in 0.4.8: use Data.Enumerator.List.map
instead
mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b
Deprecated in 0.4.8: use Data.Enumerator.List.mapM
instead
Since: 0.4.3
concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b
Deprecated in 0.4.8: use Data.Enumerator.List.concatMap
instead
Since: 0.4.3
concatMapM :: Monad m => (ao -> m [ai]) -> Enumeratee ao ai m b
Deprecated in 0.4.8: use Data.Enumerator.List.concatMapM
instead
Since: 0.4.5
filter :: Monad m => (a -> Bool) -> Enumeratee a a m b
Deprecated in 0.4.8: use Data.Enumerator.List.filter
instead
Since: 0.4.5
filterM :: Monad m => (a -> m Bool) -> Enumeratee a a m b
Deprecated in 0.4.8: use Data.Enumerator.List.filterM
instead
Since: 0.4.5
liftFoldL :: Monad m => (b -> a -> b) -> b -> Iteratee a m b
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
Deprecated in 0.4.5: use Data.Enumerator.List.fold
instead
Since: 0.1.1