<div dir="ltr">Can I  transform a conduit so some values are passed through unchanged, but others go through the conduit?  For example:<br><div><div><br>    right :: Conduit i m o -&gt; Conduit (Either x i) m (Either x o)<br>

<br></div><div>This is named after the Control.Arrow combinator of the same name:<br><br>    right :: ArrowChoice a =&gt; a b c -&gt; a (Either d b) (Either d c)<br></div><div><br></div><div>Here&#39;s  my use case (simplified): I want to compress data with zlib-conduit, which provides:<br>

<br></div><div>    compress :: Conduit (Flush ByteString) m (Flush ByteString)<br><br></div><div>The <a href="http://hackage.haskell.org/packages/archive/conduit/latest/doc/html/Data-Conduit.html#t:Flush">Flush</a> wrapper lets me flush the compressor so it will yield cached data right away (though hurting compression a little).<br>

<br></div><div>But before compressing the data, I want to encode it, using this conduit:<br><br></div><div>    encode :: Conduit Entry m ByteString<br><br></div><div>I want to combine these, so that if I send a &#39;Flush&#39;, it bypasses &#39;encode&#39; and feeds to &#39;compress&#39;:<br>

<br></div><div>    compressEncode :: Conduit (Flush Entry) m (Flush ByteString)<br><br></div><div>Thus, I need a variant of &#39;encode&#39; that passes &#39;Flush&#39; along:<br></div><div><br>    encode&#39; :: Conduit (Flush Entry) m (Flush ByteString)<br>

<br></div><div>In my actual program, I don&#39;t use Flush, so providing a Conduit combinator just for Flush would not help me.<br><br></div><div>Is something like &#39;right&#39; possible to implement with Conduit&#39;s public API?  Here&#39;s an implementation using Data.Conduit.Internal (untested):<br>

<br>    import Control.Monad (liftM)<br>    import Data.Conduit.Internal (Pipe(..), ConduitM(..), Conduit)<br><br>    right :: Monad m =&gt; Conduit i m o -&gt; Conduit (Either x i) m (Either x o)<br>    right = ConduitM . rightPipe . unConduitM<br>

<br>    rightPipe :: Monad m<br>              =&gt; Pipe i i o () m ()<br>              -&gt; Pipe (Either x i) (Either x i) (Either x o) () m ()<br>    rightPipe p0 = case p0 of<br>        HaveOutput p c o  -&gt; HaveOutput (rightPipe p) c (Right o)<br>

        NeedInput p c     -&gt; NeedInput p&#39; (rightPipe . c)<br>          where p&#39; (Left x)  = HaveOutput (rightPipe p0) (return ()) (Left x)<br>                p&#39; (Right i) = rightPipe $ p i<br>        Done r            -&gt; Done r<br>

        PipeM mp          -&gt; PipeM $ liftM rightPipe mp<br>        Leftover p i      -&gt; Leftover (rightPipe p) (Right i)<br><br></div><div>I&#39;m wondering if we could have a Data.Conduit.Arrow module, which provides a newtype variant of Conduit that implements Arrow, ArrowChoice, etc.:<br>

<br></div><div>    import qualified Data.Conduit as C<br><br></div><div>    newtype Conduit m i o = Conduit (C.Conduit i m o)<br><br></div><div>    -- May need Monad constraints for these<br></div><div>    instance Category (Conduit m)<br>

</div><div>    instance Arrow (Conduit m)<br></div><div>    instance ArrowChoice (Conduit m)<br><br></div><div>Does &#39;Conduit&#39; follow Category, Monad, MonadTrans laws* these days?  I&#39;m not talking about Pipe in general, just the special case of it represented by the &#39;Conduit&#39; type alias:<br>

<br></div><div>    Conduit i m o = ConduitM i o m () = Pipe i i o () m ()<br><br></div><div>Or are there some thorny issues (e.g. leftovers) that make following these laws impossible in some cases?<br></div><div><br></div>

<div>Thanks for the input,<br></div><div>-Joey<br></div><div><br> * Assume functions that use Data.Conduit.Internal do so correctly.<br></div></div></div>