The newly released coroutine-enumerator package can be used as a bridge between the enumerator and monad-coroutine packages. It provides two-way conversion functions between an Iteratee and an Await-suspending coroutine, and also between an Enumerator and a Yield-suspending coroutine.<br>
<br>As a little example, the following program combines the http-enumerator, monad-coroutine, and SCC packages using the coroutine-enumerator package to print out all lines from the Hackage database containing substring "enumerator":<br>
<br>> import Control.Exception.Base (SomeException)<br>> import Control.Monad.Trans.Class (lift)<br>> <br>> import Data.ByteString (ByteString)<br>> import Data.Text.Encoding (decodeUtf8)<br>> <br>> import Network.HTTP.Enumerator<br>
> <br>> import Control.Monad.Coroutine<br>> import Control.Monad.Coroutine.SuspensionFunctors<br>> import Control.Monad.Coroutine.Nested<br>> import Control.Monad.Coroutine.Enumerator<br>> <br>> import Control.Concurrent.SCC.Sequential<br>
> <br>> main = httpRedirect (\_ _-> coroutineIteratee consumer) =<< parseUrl address<br>> <br>> address = "<a href="http://hackage.haskell.org/packages/archive/pkg-list.html">http://hackage.haskell.org/packages/archive/pkg-list.html</a>"<br>
> <br>> consumer :: Coroutine (Await [ByteString]) IO (Either SomeException ((), [ByteString]))<br>> consumer = pipe translator (consume worker) >> return (Right ((), []))<br>> <br>> translator :: Functor f => Sink IO (EitherFunctor (Await [a]) f) a -> Coroutine (EitherFunctor (Await [a]) f) IO ()<br>
> translator sink = do chunks <- liftParent await<br>> if null chunks<br>> then lift (putStrLn "END")<br>> else putList chunks sink >> translator sink<br>
> <br>> worker :: Consumer IO ByteString ()<br>> worker = toChars >-> foreach (line `having` substring "enumerator")<br>> (append (fromList "\n") >-> toStdOut)<br>
> suppress<br>> <br>> toChars :: Monad m => Transducer m ByteString Char<br>> toChars = oneToOneTransducer decodeUtf8 >-> coerce<br><br><br>Alternatively, the worker coroutine can parse the XML database and print out all elements whose any attribute value contains the substring "enumerator":<br>
<br>> worker = toChars<br>> >-> parseXMLTokens <br>> >-> foreach (xmlElementHavingTagWith (xmlAttributeValue `having` substring "enumerator") <br>> `nestedIn` xmlElementContent)<br>
> (coerce >-> toStdOut) <br>> suppress<br><br>