Data.Enumerator

enumerator-0.4.20: Reliable, high-performance processing with left-fold enumerators

Copyright | 2010-2011 John Millikin
License | MIT
Maintainer | jmillikin@gmail.com
Portability | portable
Safe Haskell | Safe
Language | Haskell98

Data.Enumerator

Contents

- Types
- Running iteratees
- Operators
- Error handling
- Miscellaneous
- Testing and debugging
- Internal interfaces

Description

For compatibility reasons, this module should imported qualified:

    import qualified Data.Enumerator as E

Synopsis

- newtype Iteratee a m b = Iteratee {
  - runIteratee :: m (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)
- run :: Monad m => Iteratee a m b -> m (Either SomeException b)
- run_ :: Monad m => Iteratee a m b -> 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
- (=$=) :: Monad m => Enumeratee a1 a2 m (Step a3 m b) -> Enumeratee a2 a3 m b -> Enumeratee a1 a3 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
- isEOF :: Monad m => Iteratee a m Bool
- tryIO :: MonadIO m => IO b -> Iteratee a m b
- liftTrans :: (Monad m, MonadTrans t, Monad (t m)) => Iteratee a m b -> Iteratee a (t m) b
- printChunks :: (MonadIO m, Show a) => Bool -> Iteratee a m ()
- enumList :: Monad m => Integer -> [a] -> Enumerator a m b
- enumLists :: Monad m => [[a]] -> Enumerator a m b
- runLists :: [[a]] -> Iteratee a Identity b -> Either SomeException b
- runLists_ :: [[a]] -> Iteratee a Identity b -> b
- module Data.Enumerator.Internal
- peek :: Monad m => Iteratee a m (Maybe a)
- last :: Monad m => Iteratee a m (Maybe a)
- length :: Monad m => Iteratee a m Integer
- liftI :: Monad m => (Stream a -> Step a m b) -> Iteratee a m b
- 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

newtype Iteratee a m b

The primary data type for this library; an iteratee consumes chunks of input from a stream until it either yields a value or encounters an error.

Compatibility note: `Iteratee` will become abstract in `enumerator_0.5`. If you depend on internal implementation details, please import `Data.Enumerator.Internal`.

Constructors

Iteratee |
Fields runIteratee :: m (Step a m b)

Instances

MonadTrans (Iteratee a) |
Monad m => Monad (Iteratee a m) |
Monad m => Functor (Iteratee a m) |
Monad m => Applicative (Iteratee a m) |
MonadIO m => MonadIO (Iteratee a m) |

type Enumerator a m b = Step a m b -> Iteratee a m b

Enumerators are sources of data, to be consumed by iteratees. Enumerators typically read from an external source (parser, handle, random generator, etc), then feed chunks into an tteratee until:

- The input source runs out of data.
- The iteratee yields a result value.
- The iteratee throws an exception.

type Enumeratee ao ai m b = Step ai m b -> Iteratee ao m (Step ai m b)

An enumeratee acts as a stream adapter; place one between an enumerator and an iteratee, and it changes the type or contents of the input stream.

Most users will want to combine enumerators, enumeratees, and iteratees using the stream combinators `joinI` and `joinE`, or their operator aliases `(=$)` and `($=)`. These combinators are used to manage how left-over input is passed between elements of the data processing pipeline.

# 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).

    import Data.Enumerator
    import Data.Enumerator.List as EL

    main = do
        result <- run (EL.iterate succ 'A' $$ EL.take 5)
        case result of
            Left exc -> putStrLn ("Got an exception: " ++ show exc)
            Right chars -> putStrLn ("Got characters: " ++ show chars)

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.

    import Data.Enumerator
    import Data.Enumerator.List as EL

    main = do
        chars <- run_ (EL.iterate succ 'A' $$ EL.take 5)
        putStrLn ("Got characters: " ++ show chars)

Since: 0.4.1

# Operators

Compatibility note: Most of these will be obsoleted by version 0.5. Please make sure your `.cabal` files have a `<0.5` limit on the `enumerator` dependency.

(>>==) :: Monad m => Iteratee a m b -> (Step a m b -> Iteratee a' m b') -> Iteratee a' m b' infixl 1

The most primitive stream operator. `iter >>== enum` returns a new iteratee which will read from `enum` before continuing.

(==<<) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b' infixr 1

    (==<<) = flip (>>==)

($$) :: Monad m => (Step a m b -> Iteratee a' m b') -> Iteratee a m b -> Iteratee a' m b' infixr 0

    ($$) = (==<<)

This is somewhat easier to read when constructing an iteratee from many processing stages. You can treat it like `(`$`)`, and read the data flow from left to right.

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' infixr 1

    (>==>) enum1 enum2 step = enum1 step >>== enum2

The moral equivalent of `(`>=>`)` for iteratees.

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' infixr 1

    (<==<) = flip (>==>)

Since: 0.1.1

(=$) :: Monad m => Enumeratee ao ai m b -> Iteratee ai m b -> Iteratee ao m b infixr 0

“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 `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 infixl 1

“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

Compatibility note: in version 0.4.15, the associativity of `($=)` was changed from `infixr 0` to `infixl 1`.

Since: 0.4.9

(=$=) :: Monad m => Enumeratee a1 a2 m (Step a3 m b) -> Enumeratee a2 a3 m b -> Enumeratee a1 a3 m b infixl 1

Composes two enumeratees.

Note that if the inner enumeratee yields left-over input, this will be discarded.

Example: converting bytes into lower-case text:

    import Data.ByteString
    import Data.Text
    import Data.Enumerator.List as EnumList
    import Data.Enumerator.Text

    decodeAndLower :: Monad m => Enumeratee ByteString Text m b
    decodeAndLower = decode utf8 =$= EnumList.map toLower

Since: 0.4.17

# Error handling

throwError :: (Monad m, Exception e) => e -> Iteratee a m b

The moral equivalent of `throwIO` for iteratees.

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.

WARNING: Within the error handler, it is difficult or impossible to know how much input the original iteratee has consumed. Users are strongly advised to wrap all uses of `catchError` with an appropriate isolation enumeratee, such as `Data.Enumerator.List.isolate` or `Data.Enumerator.Binary.isolate`, which will handle input framing even in the face of unexpected errors.

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

“Wraps” an iteratee inner in an enumeratee wrapper. The resulting iteratee will consume wrapper’s input type and yield inner’s output type.

See the documentation for (`=$`).

    joinI (enum $$ iter) = enum =$ iter

joinE :: Monad m => Enumerator ao m (Step ai m b) -> Enumeratee ao ai m b -> Enumerator ai m b

“Wraps” an enumerator inner in an enumeratee wrapper. The resulting enumerator will generate wrapper’s output type.

See the documentation for (`$=`).

    joinE enum enee = enum $= enee

Since: 0.4.5

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.

isEOF :: Monad m => Iteratee a m Bool

Check whether a stream has reached EOF. Note that if the stream is not at EOF, `isEOF` may cause data to be read from the enumerator.

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 passed to `throwError`.

Since: 0.4.9

liftTrans :: (Monad m, MonadTrans t, Monad (t m)) => Iteratee a m b -> Iteratee a (t m) b

Lift an `Iteratee` onto a monad transformer, re-wrapping its inner monadic values.

Since: 0.1.1

# Testing and debugging

printChunks

Arguments

:: (MonadIO m, Show a) |
=> Bool | Print empty chunks
-> Iteratee a m () |

Print chunks as they're received from the enumerator, optionally printing empty chunks.

enumList :: Monad m => Integer -> [a] -> Enumerator a m b

``enumList` n xs` enumerates xs as a stream, passing n inputs per chunk. This is primarily useful for testing, debugging, and REPL exploration.

Compatibility note: In version 0.5, `enumList` will be changed to the type:

    enumList :: Monad m => [a] -> Enumerator a m b

enumLists :: Monad m => [[a]] -> Enumerator a m b

``enumLists` xs` enumerates xs as a stream, where each element is a separate chunk. This is primarily useful for testing and debugging.

Since: 0.4.15

runLists :: [[a]] -> Iteratee a Identity b -> Either SomeException b

Run an iteratee with the given input, and return either the final value (if it succeeded) or the error (if it failed).

Since: 0.4.15

runLists_ :: [[a]] -> Iteratee a Identity b -> b

Like `runLists`, except errors are converted to exceptions and thrown.

Since: 0.4.15

# Internal interfaces

This module export will be removed in version 0.5. If you depend on internal implementation details, please import `Data.Enumerator.Internal` directly.

module Data.Enumerator.Internal

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.

liftI :: Monad m => (Stream a -> Step a m b) -> Iteratee a m b

Deprecated: Use `continue` instead

Deprecated in 0.4.5: use `continue` instead

head :: Monad m => Iteratee a m (Maybe a)

Deprecated: Use `head` instead

Deprecated in 0.4.5: use `head` instead

drop :: Monad m => Integer -> Iteratee a m ()

Deprecated: Use `drop` instead

Deprecated in 0.4.5: use `drop` instead

dropWhile :: Monad m => (a -> Bool) -> Iteratee a m ()

Deprecated: Use `dropWhile` instead

Deprecated in 0.4.5: use `dropWhile` instead

span :: Monad m => (a -> Bool) -> Iteratee a m [a]

Deprecated: Use `takeWhile` instead

Deprecated in 0.4.5: use `takeWhile` instead

break :: Monad m => (a -> Bool) -> Iteratee a m [a]

Deprecated: Use `takeWhile` instead

Deprecated in 0.4.5: use `takeWhile` instead

consume :: Monad m => Iteratee a m [a]

Deprecated: Use `consume` instead

Deprecated in 0.4.5: use `consume` instead

foldl :: Monad m => (b -> a -> b) -> b -> Iteratee a m b

Deprecated: Use Data.Enumerator.List.fold instead

Deprecated in 0.4.8: use `fold` instead

Since: 0.4.5

foldl' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b

Deprecated: Use Data.Enumerator.List.fold instead

Deprecated in 0.4.8: use `fold` instead

Since: 0.4.5

foldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b

Deprecated: Use Data.Enumerator.List.foldM instead

Deprecated in 0.4.8: use `foldM` instead

Since: 0.4.5

iterate :: Monad m => (a -> a) -> a -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.iterate instead

Deprecated in 0.4.8: use `iterate` instead

Since: 0.4.5

iterateM :: Monad m => (a -> m a) -> a -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.iterateM instead

Deprecated in 0.4.8: use `iterateM` instead

Since: 0.4.5

repeat :: Monad m => a -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.repeat instead

Deprecated in 0.4.8: use `repeat` instead

Since: 0.4.5

repeatM :: Monad m => m a -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.repeatM instead

Deprecated in 0.4.8: use `repeatM` instead

Since: 0.4.5

replicate :: Monad m => Integer -> a -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.replicate instead

Deprecated in 0.4.8: use `replicate` instead

Since: 0.4.5

replicateM :: Monad m => Integer -> m a -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.replicateM instead

Deprecated in 0.4.8: use `replicateM` instead

Since: 0.4.5

generateM :: Monad m => m (Maybe a) -> Enumerator a m b

Deprecated: Use Data.Enumerator.List.generateM instead

Deprecated in 0.4.8: use `generateM` instead

Since: 0.4.5

map :: Monad m => (ao -> ai) -> Enumeratee ao ai m b

Deprecated: Use Data.Enumerator.List.map instead

Deprecated in 0.4.8: use `map` instead

mapM :: Monad m => (ao -> m ai) -> Enumeratee ao ai m b

Deprecated: Use Data.Enumerator.List.mapM instead

Deprecated in 0.4.8: use `mapM` instead

Since: 0.4.3

concatMap :: Monad m => (ao -> [ai]) -> Enumeratee ao ai m b

Deprecated: Use Data.Enumerator.List.concatMap instead

Deprecated in 0.4.8: use `concatMap` instead

Since: 0.4.3

concatMapM :: Monad m => (ao -> m [ai]) -> Enumeratee ao ai m b

Deprecated: Use Data.Enumerator.List.concatMapM instead

Deprecated in 0.4.8: use `concatMapM` instead

Since: 0.4.5

filter :: Monad m => (a -> Bool) -> Enumeratee a a m b

Deprecated: Use Data.Enumerator.List.filter instead

Deprecated in 0.4.8: use `filter` instead

Since: 0.4.5

filterM :: Monad m => (a -> m Bool) -> Enumeratee a a m b

Deprecated: Use Data.Enumerator.List.filterM instead

Deprecated in 0.4.8: use `filterM` instead

Since: 0.4.5

liftFoldL :: Monad m => (b -> a -> b) -> b -> Iteratee a m b

Deprecated: Use Data.Enumerator.List.fold instead

Deprecated in 0.4.5: use `fold` instead

Since: 0.1.1

liftFoldL' :: Monad m => (b -> a -> b) -> b -> Iteratee a m b

Deprecated: Use Data.Enumerator.List.fold instead

Deprecated in 0.4.5: use `fold` instead

Since: 0.1.1

liftFoldM :: Monad m => (b -> a -> m b) -> b -> Iteratee a m b

Deprecated: Use Data.Enumerator.List.foldM instead

Deprecated in 0.4.5: use `foldM` instead

Since: 0.1.1