This is Gabriel, who posted Pipes. I've been working with Paolo and we have a more elegant implementation in the works that is even more powerful and typesafe than his original proposal. The short answer to your question is that the final implementation is a superset of the original Pipes and you can write the same code as before with identical behavior and semantics.

I can even summarize it pretty simply here. Await and yield statements are the only ways a pipe can give up control, so we attach to each one a fallback if the upstream or downstream pipe terminates. The fallback downgrades a pipe permanently and it can no longer repeat the failed action. A failed await downgrades a pipe to a producer and a failed yield downgrades a pipe to a consumer. If a producer fails to yield or a consumer fails to await, they are downgraded to the base monad, which can no longer fail.

Consumers and producers are now separate types and the are not exposed. They are the same as the type pipe type except missing the Await or Yield constructor. This is necessary, at least for the producer type, since there is no input type for pipes that can prohibit await statements.

Await and yield statements default to termination as their fall back behavior, which is the same behavior as before. Await and yield will be typeclassed to work in downgraded states that support them. However you can now optionally provide your own fallback as soon as we come up with a sexier name than tryAwait or tryYield.

I have to still verify that Pipes still form a category with this extension, but it seems very likely. It's also 100% typesafe and uses the types to enforce the downgrade rather than booleans and a programmer proven invariant.

Edit: Some functioning code to whet your appetite (Checkout the "try" branch from the github repository to use the extension):