Control.Pipe.PutbackPipe #3

wants to merge 3 commits into


None yet

2 participants

ierton commented Mar 26, 2012

Hi, Paolo. As I wrote in my last email, here is the implementation of PutbackPipe. I suggest using it instead of ChunkPipe.

Best Regards,


Merged, and removed ChunkPipe. Thanks!

@pcapriotti pcapriotti closed this Mar 31, 2012
ierton commented Apr 4, 2012

2012/3/31 Paolo Capriotti

Merged, and removed ChunkPipe. Thanks!

Reply to this email directly or view it on GitHub:
#3 (comment)

Hi, Paolo! I've detected an issue regarding putback pipes. It turns
out, that user can't putback anything and get it back after
unsuccessful call to tryAwaitPB. But library doesn't protect against
that and doesn't handle that well. I plan to fix that by implementing
my own queue and stop using loopP. Could you please delay release of
pipes-extra if you have such plans?



Ah, I see the problem now. loopP is not actually a well-defined operation modulo the equivalence relation on pipes explained here. The net effect is that pipes that should be "equal" are actually distinguished by loopP.

The workaround for now is to define PutbackPipe as Pipe (Either a a) (Either b a), and define awaitPB = liftM (either id id) await. However, I think I'm going to change loopP so that it always fails to await in an error handler, and then this definition won't work either.

@pcapriotti pcapriotti reopened this Apr 5, 2012

A possible solution to this problem is to introduce a Transform constructor to Pipe. The idea is that Transform t is an infinite pipe that always transforms its input using the function t. It is very similar to forever $ await >>= yield . t, but differs (slightly) in the way it deals with upstream failure.

You can check it in my transform branch of pipes-core. I think PutbackPipe works correctly with this new primitive. Please let me know what you think.

ierton commented Apr 6, 2012

Hi, Paolo. I've looked inside transform branch. The idea is clear but I am afraid it will take some time for me to figure out the whole picture - I feel that I need to carefully walk across your pipe-category-laws wiki to improve my type-theory skills:) Still let me suggest another solution - I've used StateT to emulate loopP's internal queue and I think it does the trick.

@pcapriotti pcapriotti added a commit that referenced this pull request Apr 7, 2012
@pcapriotti Modify PutbackPipe to work around loopP limitation (#3).
loopP can distinguish equivalent pipes that await in an error handler.

Using a composite pipe in a call to loopP can result in unexpected
behavior after upstream failure.

This commit works around the problem by modifying PutbackPipe so that
loopP is applied to a single pipe.

Please check the above commit and see if it fixes the issue. It is only meant as a workaround until I figure out a clean solution. I think this is a minor issue, so I might decide to release pipes-* anyway.

I also merged the MonadIO instance. Thanks!

@pcapriotti pcapriotti closed this Apr 7, 2012
ierton commented Apr 9, 2012

I've checked your fix - works fine, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment