Haskell/Libraries/IO

The IO Library
Here, we'll explore the most commonly used elements of the  module.

Most of the IO functions are self-explanatory. The  and   functions open and close a file, respectively. The  argument determines the mode for opening the file. tests for end-of file. and  read a character or line (respectively) from a file. reads the entire file. The,  , and   variants read from standard input. prints a character to a file;  prints a string; and   prints a string with a newline character at the end. The variants without the  prefix work on standard output. The  and   functions read and write an entire file without having to open it first.

Bracket
The  function comes from the   module. It helps perform actions safely.

Consider a function that opens a file, writes a character to it, and then closes the file. When writing such a function, one needs to be careful to ensure that, if there were an error at some point, the file is still successfully closed. The  function makes this easy. It takes three arguments: The first is the action to perform at the beginning. The second is the action to perform at the end, regardless of whether there's an error or not. The third is the action to perform in the middle, which might result in an error. For instance, our character-writing function might look like:

This will open the file, write the character, and then close the file. However, if writing the character fails,  will still be executed, and the exception will be reraised afterwards. That way, you don't need to worry too much about catching the exceptions and about closing all of your handles.

A File Reading Program
We can write a simple program that allows a user to read and write files. The interface is admittedly poor, and it does not catch all errors (such as reading a non-existent file). Nevertheless, it should give a fairly complete example of how to use IO. Enter the following code into "FileRead.hs," and compile/run:

What does this program do? First, it issues a short string of instructions and reads a command. It then performs a case switch on the command and checks first to see if the first character is a `q.' If it is, it returns a value of unit type.

If the first character of the command wasn't a `q,' the program checks to see if it was an 'r' followed by some string that is bound to the variable. It then tells you that it's reading the file, does the read and runs  again. The check for `w' is nearly identical. Otherwise, it matches, the wildcard character, and loops to.

The  function uses the   function to make sure there are no problems reading the file. It opens a file in, reads its contents and prints the first 100 characters (the  function takes an integer $$n$$ and a list and returns the first $$n$$ elements of the list).

The  function asks for some text, reads it from the keyboard, and then writes it to the specified file.

The program has one major problem: it will die if you try to read a file that doesn't already exist or if you specify some bad filename like. You may think that the calls to  in   and   should take care of this, but they don't. They only catch exceptions within the main body, not within the startup or shutdown functions ( and, in these cases). To make this completely reliable, we would need a way to catch exceptions raised by.