# Enumerator and iteratee

An enumerator is something that knows how to generate a list and an iteratee is something that does one step in processing another piece of the big list. E.g. to sum up all elements of a list, we do <pre-haskell> foldl (+) 0 xs </pre-haskell> Then <code-haskell>foldl</code-haskell> is the enumerator and <code-haskell>((+),0)</code-haskell> is the iteratee.

Clearly the function that sums the current element with the accumulator, <code-haskell>(+)</code-haskell>, doesn't know or care from which collection the elements are coming from. The initial seed, <code-haskell>0</code-haskell>, is again unaware of the collection. That achieves the separation of concerns: fold (aka, enumerator) has the intimate knowledge of the collection and how to get to the next element; iteratee knows what to do with the current element.

## Definition

Do not rely on the <code-haskell>foldl</code-haskell> analogy too firmly, it is misleading. <code-haskell>((+),0)</code-haskell> is F-algebra and <code-haskell>foldl (+) 0</code-haskell> is catamorphism. But iteratee is different, it is automaton. From this point of view, enumerator sends elements of a list from head to tail sequentially as input messages to iteratee. If iteratee finishes, it outputs an accumulator. If iteratee continues, it outputs nothing (i.e. <code-haskell>()</code-haskell>).

So, a set of states of iteratee is divided into subsets "Done" and "Next". Done-state means that automaton finished consuming a list, i.e. automaton is dead. Next-state means that you can give an input message and obtain the same automaton in a new state. <pre-haskell> data Iteratee i o

``` = Done o
| Next (i -> Iteratee i o)
```

The distinct feature of iteratee is that it can say after which list element an iteratee finishes. An iteratee says this by sending "Done" to an enumerator. Then the enumerator can close a file or a socket (a stream) where a list of characters is read from. Lazy I/O, which uses lazy lists, close a stream only when the stream is exhausted.

The drawback is that enumerator can not tell iteratee that a list is exhausted. An <code-haskell>Iteratee</code-haskell> consumes only infinite lists. You can remedy this by assuming <pre-haskell> i == Maybe i' </pre-haskell> where <code-haskell>i'</code-haskell> is a type of list elements. <code-haskell>Nothing</code-haskell> given to iteratee signals that the list is exhausted.

Here is a sample enumerator that takes input messages from a file: <pre-haskell> enumerator :: FilePath -> Iteratee (Maybe Char) o -> IO o enumerator file it = withFile file ReadMode

``` \$ \h -> fix (\rc it -> case it of
Done o -> return o
Next f -> do
eof <- hIsEOF h
case eof of
False -> do
c <- hGetChar h
rc (f (Just c))
True -> rc (f Nothing)
) it
```

## Functions

``` fmap f = fix \$ \rc s -> case s of
Done o -> Done (f o)
Next g -> Next (rc . g)
```

``` return = Done
it0 >>= it1 = fix (\rc s -> case s of
Done o -> it1 o
Next g -> Next (rc . g)
) it0
```

``` id = arr0 id
it1 . it0 = fix (\rc1 it1 -> case it1 of
Done c -> Done c
Next f1 -> fix (\rc0 it0 -> case it0 of
Done b -> rc1 (f1 b)
Next f0 -> Next (rc0 . f0)
) it0
) it1
```