<div dir="ltr">Only you can tell if this is what you want. It doesn't look horribly broken at a glance. Try it out and see!<div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span style="font-size:12.8px">it's the </span><font face="monospace, monospace" style="font-size:12.8px">r</font><span style="font-size:12.8px"> I want to get my hands on, not the </span><font face="monospace, monospace" style="font-size:12.8px">u</font><span style="font-size:12.8px">.</span></blockquote><div><br></div><div>Look at the pipe composition operator<br></div><div><br></div><div><font face="monospace, monospace">(>+>) ::</font></div><div><font face="monospace, monospace"><span class=""> </span><span class="" style="color:rgb(0,0,0)">Pipe</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">l</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">a</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">b</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">r0</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">m</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">r1</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:red">-></span></font></div><div><font face="monospace, monospace"><span class="" style="color:rgb(0,0,0)"> Pipe</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">Void</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">b</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">c</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">r1</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">m</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">r2</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:red">-></span></font></div><div><font face="monospace, monospace"><span class="" style="color:rgb(0,0,0)"> Pipe</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">l</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">a</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">c</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">r0</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">m</span><span style="color:rgb(0,0,0)"> </span><span class="" style="color:rgb(0,0,0)">r2</span></font></div><div><font face="monospace, monospace"><span class="" style="color:rgb(0,0,0)"><br></span></font></div><div><span class="" style="color:rgb(0,0,0)"><font face="arial, helvetica, sans-serif">Here you see that not only do (a b) and (b c) connect to make (a c), but also (r0 m r1) and (r1 m r2) connect to make (r0 m r2). So r1 is the first argument's r, and the second argument's u. If you are writing a Pipe that will sit downstream of another pipe with return type x, then you can get an (Either x i) using awaitE, which will indicate whether the upstream pipe terminated or yielded.</font></span></div></div><div class="gmail_extra"><br clear="all"><div><div class="gmail_signature">-- Dan Burton</div></div>
<br><div class="gmail_quote">On Sat, Feb 13, 2016 at 1:37 AM, David Turner <span dir="ltr"><<a href="mailto:dct25-561bs@mythic-beasts.com" target="_blank">dct25-561bs@mythic-beasts.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Thanks Dan, some useful pointers there.<div><br></div><div>Looking at the Pipes level, there's</div><div><br></div><div><font face="monospace, monospace">ConduitM i o m r = forall b. (r -> Pipe i i o () m b) -> Pipe i i o () m b</font></div><div><font face="monospace, monospace"> = forall b. ContT b (Pipe i i o () m) r</font></div><div><br></div><div>(not sure if the comparison with <font face="monospace, monospace">ContT</font> is helpful yet...)</div><div><br></div><div>I see what you mean about the upstream return type <font face="monospace, monospace">u</font> always being <font face="monospace, monospace">()</font> with <font face="monospace, monospace">ConduitM</font>, although it's the <font face="monospace, monospace">r</font> I want to get my hands on, not the <font face="monospace, monospace">u</font>. I think that means a combinator like <font face="monospace, monospace">awaitE </font>can't work in <font face="monospace, monospace">ConduitM</font> as it can't depend on the return type of the upstream <font face="monospace, monospace">ConduitM</font>.</div><div><br></div><div>Looking at how (=$=) is defined, I tried this:</div><div><br></div><div><div><font face="monospace, monospace">fuseEither :: Monad m => ConduitM a b m u -> ConduitM b c m d -> ConduitM a c m (Either u d)</font></div><div><font face="monospace, monospace">fuseEither (ConduitM left0) (ConduitM right0) = ConduitM $ \rest -></font></div><div><font face="monospace, monospace"> let goRight final left right =</font></div><div><font face="monospace, monospace"> case right of</font></div><div><font face="monospace, monospace"> HaveOutput p c o -> HaveOutput (recurse p) (c >> final) o</font></div><div><font face="monospace, monospace"> NeedInput rp rc -> goLeft rp rc final left</font></div><div><font face="monospace, monospace"> Done r2 -> PipeM (final >> return (rest (Right r2)))</font></div><div><font face="monospace, monospace"> PipeM mp -> PipeM (liftM recurse mp)</font></div><div><font face="monospace, monospace"> Leftover right' i -> goRight final (HaveOutput left final i) right'</font></div><div><font face="monospace, monospace"> where</font></div><div><font face="monospace, monospace"> recurse = goRight final left</font></div><div><font face="monospace, monospace"><br></font></div><div><font face="monospace, monospace"> goLeft rp rc final left =</font></div><div><font face="monospace, monospace"> case left of</font></div><div><font face="monospace, monospace"> HaveOutput left' final' o -> goRight final' left' (rp o)</font></div><div><font face="monospace, monospace"> NeedInput left' lc -> NeedInput (recurse . left') (recurse . lc)</font></div><div><font face="monospace, monospace"> Done r1 -> PipeM (final >> return (rest (Left r1)))</font></div><div><font face="monospace, monospace"> PipeM mp -> PipeM (liftM recurse mp)</font></div><div><font face="monospace, monospace"> Leftover left' i -> Leftover (recurse left') i</font></div><div><font face="monospace, monospace"> where</font></div><div><font face="monospace, monospace"> recurse = goLeft rp rc final</font></div><div><font face="monospace, monospace"> in goRight (return ()) (left0 Done) (right0 Done)</font></div></div><div><br></div><div><br></div><div>The only difference from <font face="monospace, monospace">(=$=)</font> is the two <font face="monospace, monospace">Done </font>cases: the one in <font face="monospace, monospace">goRight </font>now passes <font face="monospace, monospace">Right r2</font> back to <font face="monospace, monospace">rest </font>instead of <font face="monospace, monospace">r2</font> itself, and the one in <font face="monospace, monospace">goLeft </font>passes <font face="monospace, monospace">Left r1</font> back instead of continuing with another call to <font face="monospace, monospace">goRight</font>. Much to my surprise, this actually compiled! But I've no idea whether there are any bad consequences of this - indeed, I've no real idea what's going on here at all, I just took a punt.</div><div><br></div><div>Is this horribly broken or is this exactly what I want?</div><div><br></div><div>Cheers,</div><div><br></div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On 13 February 2016 at 01:33, Dan Burton <span dir="ltr"><<a href="mailto:danburton.email@gmail.com" target="_blank">danburton.email@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><a name="-1958094280_-560706964_-532126307_t:Source" style="font-size:13px;color:rgb(0,0,0);margin:0px;padding:0px;font-weight:bold;font-family:monospace;line-height:16.12px">Source</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> m o = </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> () o m ()</span><span style="font-size:12.8px">; why is </span><a name="-1958094280_-560706964_-532126307_t:Source" style="color:rgb(0,0,0);font-size:13px;margin:0px;padding:0px;font-weight:bold;font-family:monospace;line-height:16.12px">Source</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> m o</span><span style="font-size:12.8px"> not </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="color:rgb(171,105,84);font-size:13px;margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> Void o m ()</span><span style="font-size:12.8px">?</span></blockquote><div><br></div><div>I can't think of a really good answer to this, but here's a mediocre answer: you can always "step" a ConduitM that is blocked on trivial input. So the promise of a Source is not that it never blocks, but rather, that it only blocks in such a way that it is trivial to unblock.</div><div><br></div><div>You may like the Producer type synonym better:</div><div><pre style="color:rgb(0,0,0)"><span style="color:blue">type</span> <span>Producer</span> <span>m</span> <span>o</span> <span style="color:red">=</span> <span style="color:blue">forall</span> <span>i</span><span>.</span> <span>ConduitM</span> <span>i</span> <span>o</span> <span>m</span> <span>()</span></pre></div><div>When you have a Producer m o, it can be instantiated to ConduitM Void o m (), because you can select i = Void.</div><div><br></div><div>Now for your main question...</div><div><br></div>So the thing about ConduitM composition is that the "upstream result" must be (). If you peel away the ConduitM layer of abstraction and take a look at Data.Conduit.Internal.Pipe, you'll find the operator you're looking for:<div><br></div><div><a href="http://hackage.haskell.org/package/conduit-1.2.6.1/docs/src/Data-Conduit-Internal-Pipe.html#awaitE" target="_blank">http://hackage.haskell.org/package/conduit-1.2.6.1/docs/src/Data-Conduit-Internal-Pipe.html#awaitE</a><br></div><div><br></div><div><font face="monospace, monospace">awaitE :: <span style="color:rgb(0,0,0)">Pipe</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">l</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">i</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">o</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">u</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">m</span><span style="color:rgb(0,0,0)"> </span><span style="color:red">(</span><span style="color:rgb(0,0,0)">Either</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">u</span><span style="color:rgb(0,0,0)"> </span><span style="color:rgb(0,0,0)">i</span><span style="color:red">)</span></font></div><div><font face="monospace, monospace"><span style="color:red"><br></span></font></div>I'm not quite sure how to surface this into the ConduitM level of abstraction. </div><div class="gmail_extra"><br clear="all"><div><div>-- Dan Burton</div></div>
<br><div class="gmail_quote"><div><div>On Fri, Feb 12, 2016 at 12:40 PM, David Turner <span dir="ltr"><<a href="mailto:dct25-561bs@mythic-beasts.com" target="_blank">dct25-561bs@mythic-beasts.com</a>></span> wrote:<br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div><div dir="ltr">Hi,<div><br></div><div>I've got a conduit thing that yields infinitely many values and never exits, which I've given the type <a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;margin:0px;padding:0px;text-decoration:none;color:rgb(171,105,84);font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> () o m Void</span> - a bit like <a name="-1958094280_-560706964_-532126307_t:Source" style="font-size:13px;margin:0px;padding:0px;font-weight:bold;color:rgb(0,0,0);font-family:monospace;line-height:16.12px">Source</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> m o = </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;margin:0px;padding:0px;text-decoration:none;color:rgb(171,105,84);font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> () o m ()</span> except that it can't exit due to the <span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)">Void</span>.</div><div><br></div><div>(One side-question: why is <a name="-1958094280_-560706964_-532126307_t:Source" style="font-size:13px;color:rgb(0,0,0);margin:0px;padding:0px;font-weight:bold;font-family:monospace;line-height:16.12px">Source</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> m o</span> not <a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> Void o m ()</span>?)</div><div><br></div><div>I would now like to get the first item it yields; I'm currently using <font face="monospace, monospace">Data.Conduit.List.head</font> but of course this returns a <font face="monospace, monospace">Maybe o</font> in case the upstream thing exits. Is there a way to do this without that <font face="monospace, monospace">Maybe</font>? I can't see anything obvious, but nor can I think of a terribly good reason why not.<br></div><div><br></div><div>One thing that I was pondering was a kind of fuse operator with a type like ...</div><div><br></div><div><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;margin:0px;padding:0px;text-decoration:none;color:rgb(171,105,84);font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> a b m r1 -> </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;margin:0px;padding:0px;text-decoration:none;color:rgb(171,105,84);font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> b c m r2 -> </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;margin:0px;padding:0px;text-decoration:none;color:rgb(171,105,84);font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> a c m (Either r1 r2)</span></div><div><br></div><div>... which returns the result of whichever thing exits first. Does such a thing exist? Does it even make sense? If it existed, I think I could use it here as it'd specialise to</div><div><br></div><div><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> () o m Void -> </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> o Void m o -> </span><a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> () Void m (Either Void o)</span><br></div><div><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"><br></span></div><div>and of course <span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)">(Either Void o)</span> is isomorphic to <span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)">o</span> so I'd be home and dry.</div><div><br></div><div>Having written this, I'm now also struggling to work out what the thing of type <a href="https://hackage.haskell.org/package/conduit-1.2.6/docs/Data-Conduit.html#t:ConduitM" style="font-size:13px;color:rgb(171,105,84);margin:0px;padding:0px;text-decoration:none;font-family:monospace;line-height:16.12px" target="_blank">ConduitM</a><span style="font-size:13px;color:rgb(0,0,0);font-family:monospace;line-height:16.12px;background-color:rgb(240,240,240)"> o Void m o</span> would be. Maybe I'm going about this all the wrong way, or maybe I'm just confused?</div><div><br></div><div>Any help greatly appreciated!</div><div><br></div><div>Cheers,</div><div><br></div><div>David</div><div><br></div><div><br></div></div>
<br></div></div>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org" target="_blank">Haskell-Cafe@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a><br>
<br></blockquote></div><br></div>
</blockquote></div><br></div>
</div></div></blockquote></div><br></div>