Module documentation for 1.1.9

resourcet

Proper exception handling, especially in the presence of asynchronous
exceptions, is a non-trivial task. But such proper handling is absolutely vital
to any large scale application. Leaked file descriptors or database connections
will simply not be an option when writing a popular web application, or a high
concurrency data processing tool. So the question is, how do you deal with it?

The standard approach is the bracket pattern, which appears throughout much of
the standard libraries. withFile uses the bracket pattern to safely wrap up
openFile and closeFile, guaranteeing that the file handle will be closed no
matter what. This approach works well, and I highly recommend using it.

However, there's another approach available: the resourcet
package. If the bracket pattern
is so good, why do we need another one? The goal of this post is to answer that
question.

What is ResourceT

ResourceT is a monad transformer which creates a region of code where you can safely allocate resources. Let's write a simple example program: we'll ask the user for some input and pretend like it's a scarce resource that must be released. We'll then do something dangerous (potentially introducing a divide-by-zero error). We then want to immediately release our scarce resource and perform some long-running computation.

Try entering a valid value, such as 3, and then enter 0. Notice that in both cases the "Freeing scarce resource" message is printed. And by using release before somethingElse, we guarantee that the resource is freed before running the potentially long process.

In this specific case, we could easily represent our code in terms of bracket with a little refactoring.

What ResourceT adds

The bracket pattern is designed with nested resource allocations. For example, consider the following program which copies data from one file to another. We'll open up the source file using withFile, and then nest within it another withFile to open the destination file, and finally do the copying with both file handles.

But now, let's tweak this a bit. Instead of reading from a single file, we want to read from two files and concatenate them. We could just have three nested withFile calls, but that would be inefficient: we'd have two Handles open for reading at once, even though we'll only ever need one. We could restructure our program a bit instead: put the withFile for the output file on the outside, and then have two calls to withFile for the input files on the inside.

But consider a more complicated example. Instead of just a single destination file, let's say we want to break up our input stream into chunks of, say, 50 bytes each, and write each chunk to successive output files. We now need to interleave allocations and freeings of both the source and destination files, and we cannot statically know exactly how the interleaving will look, since we don't know the size of the files at compile time.

This is the kind of situation that resourcet solves well (we'll demonstrate in the next section). As an extension of this, we can write library functions which allow user code to request arbitrary resource allocations, and we can guarantee that they will be cleaned up. A prime example of this is in WAI (Web Application Interface). The user application may wish to allocate some scarce resources (such as database statements) and use them in the generation of the response body. Using ResourceT, the web server can guarantee that these resources will be cleaned up.

Interleaving with conduit

Let's demonstrate the interleaving example described above. To simplify the code, we'll use the conduit package for the actual chunking implementation. Notice when you run the program that there are never more than two file handles open at the same time.

resourcet is not conduit

resourcet was originally created in the process of writing the conduit package.
As a result, many people have the impression that these two concepts are
intrinsically linked. In fact, this is not true: each can be used separately
from the other. The canonical demonstration of resourcet combined with conduit
is the file copy function:

Likewise, resourcet can be freely used for more flexible resource management without touching conduit. In other words, these two libraries are completely orthogonal and, while they complement each other nicely, can certainly be used separately.

Conclusion

ResourceT provides you with a flexible means of allocating resources in an exception safe manner. Its main advantage over the simpler bracket pattern is that it allows interleaving of allocations, allowing for more complicated programs to be created efficiently. If your needs are simple, stick with bracket. If you have need of something more complex, resourcet may be your answer.