Some of the simple finalization examples could be easily converted into HUnit tests. We use a `Reader` monad with an `IORef` containing a list of "actions" like "open file", "close file" and "exception" to keep track of what happens during pipeline execution.
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.