The bracket function captures a common allocate, compute, deallocate
idiom in which the deallocation step must occur even in the case of an
error during computation. This is similar to try-catch-finally in Java.

This version handles only IO errors, as defined by Haskell 98.
The version of bracket in Control.Exception handles all exceptions,
and should be used instead.