title: Wrapping conduit in ExceptT
body: <p>What is a good way to wrap a conduit in <code>ExceptT</code>? The approach should stop the processing when there is an error, and extract the error message. Here is a toy code without error-handling - it just silently stops:</p>
  
  <pre><code>import Data.Conduit as C
  import Data.ByteString as BS
  import Control.Monad
  import Control.Monad.IO.Class
  import Data.Text as T
  
  -- just a dummy processing to simulate errors
  process :: BS.ByteString -&gt; Either (Int,T.Text) BS.ByteString
  process inp = if (BS.null inp) then Left $ (1,"Empty input") else Right inp
  
  -- silent processing - stops on error but doesn't tell us what it is
  sink :: MonadIO m =&gt; Consumer BS.ByteString m ()
  sink = do
         bs &lt;- await
         case bs of
          Just val -&gt; do
              let msg = process val
              case msg of  
                Left _ -&gt; return ()
                Right x -&gt; (liftIO $ return x) &gt;&gt; sink
          Nothing -&gt; return ()
  </code></pre>
  
  <p>How could we change the type signature of <code>sink</code> to something like below?</p>
  
  <pre><code>sink :: MonadIO m =&gt; ExceptT e m (Consumer BS.ByteString m ()) 
  </code></pre>
  
  <p>In case of <code>Left</code>, it will be nice to break out of the pipeline, and return the error message to top.
  I read this <a href="https://ocharles.org.uk/blog/posts/2012-07-24-in-praise-of-EitherT.html" rel="nofollow noreferrer">blog post</a> but haven't understood it well enough yet to apply it to conduit (which also has complicated type signature). I will like to apply the proposed approach <a href="https://stackoverflow.com/a/11417819/986475">here</a> to conduit - it seems <code>EitherT</code> suggested in the approach has now been subsumed by <code>ExceptT</code>.</p>