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 &quot;enumerator&quot;:<br>
<br>&gt; import Control.Exception.Base (SomeException)<br>&gt; import Control.Monad.Trans.Class (lift)<br>&gt; <br>&gt; import Data.ByteString (ByteString)<br>&gt; import Data.Text.Encoding (decodeUtf8)<br>&gt; <br>&gt; import Network.HTTP.Enumerator<br>
&gt; <br>&gt; import Control.Monad.Coroutine<br>&gt; import Control.Monad.Coroutine.SuspensionFunctors<br>&gt; import Control.Monad.Coroutine.Nested<br>&gt; import Control.Monad.Coroutine.Enumerator<br>&gt; <br>&gt; import Control.Concurrent.SCC.Sequential<br>
&gt; <br>&gt; main = httpRedirect (\_ _-&gt; coroutineIteratee consumer) =&lt;&lt; parseUrl address<br>&gt; <br>&gt; address = &quot;<a href="http://hackage.haskell.org/packages/archive/pkg-list.html">http://hackage.haskell.org/packages/archive/pkg-list.html</a>&quot;<br>
&gt; <br>&gt; consumer :: Coroutine (Await [ByteString]) IO (Either SomeException ((), [ByteString]))<br>&gt; consumer = pipe translator (consume worker) &gt;&gt; return (Right ((), []))<br>&gt; <br>&gt; translator :: Functor f =&gt; Sink IO (EitherFunctor (Await [a]) f) a -&gt; Coroutine (EitherFunctor (Await [a]) f) IO ()<br>
&gt; translator sink = do chunks &lt;- liftParent await<br>&gt;                      if null chunks<br>&gt;                         then lift (putStrLn &quot;END&quot;)<br>&gt;                         else putList chunks sink &gt;&gt; translator sink<br>
&gt;          <br>&gt; worker :: Consumer IO ByteString ()<br>&gt; worker = toChars &gt;-&gt; foreach (line `having` substring &quot;enumerator&quot;)<br>&gt;                              (append (fromList &quot;\n&quot;) &gt;-&gt; toStdOut)<br>
&gt;                              suppress<br>&gt; <br>&gt; toChars :: Monad m =&gt; Transducer m ByteString Char<br>&gt; toChars = oneToOneTransducer decodeUtf8 &gt;-&gt; 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 &quot;enumerator&quot;:<br>
<br>&gt; worker = toChars<br>&gt;          &gt;-&gt; parseXMLTokens <br>&gt;          &gt;-&gt; foreach (xmlElementHavingTagWith (xmlAttributeValue `having` substring &quot;enumerator&quot;) <br>&gt;                       `nestedIn` xmlElementContent)<br>
&gt;                      (coerce &gt;-&gt; toStdOut) <br>&gt;                      suppress<br><br>