Online Book Reader

Home Category

Learn You a Haskell for Great Good! - Miran Lipovaca [79]

By Root 411 0
handle and closes it. bracket makes sure that this happens even if an exception is raised. Finally, the third parameter to bracket takes a handle and applies the function f to it, which takes a file handle and does stuff with that handle, like reading from or writing to the corresponding file.

Grab the Handles!


Just as hGetContents works like getContents but for a specific file, functions like hGetLine, hPutStr, hPutStrLn, hGetChar, and so on work just like their counterparts without the h but take only a handle as a parameter and operate on that specific file instead of on standard input or standard output. For example, putStrLn takes a string and returns an I/O action that will print out that string to the terminal and a newline after it. hPutStrLn takes a handle and a string and returns an I/O action that will write that string to the file associated with the handle and then put a newline after it. In the same vein, hGetLine takes a handle and returns an I/O action that reads a line from its file.

Loading files and then treating their contents as strings is so common that we have three nice little functions to make our work even easier: readFile, writeFile, and appendFile.

The readFile function has a type signature of readFile :: FilePath -> IO String. (Remember that FilePath is just a fancy name for String.) readFile takes a path to a file and returns an I/O action that will read that file (lazily, of course) and bind its contents to something as a string. It’s usually more handy than calling openFile and then calling hGetContents with the resulting handle. Here’s how we could have written our previous example with readFile:

import System.IO

main = do

contents <- readFile "girlfriend.txt"

putStr contents

Because we don’t get a handle with which to identify our file, we can’t close it manually, so Haskell does that for us when we use readFile.

The writeFile function has a type of writeFile :: FilePath -> String -> IO (). It takes a path to a file and a string to write to that file and returns an I/O action that will do the writing. If such a file already exists, it will be stomped down to zero length before being written to. Here’s how to turn girlfriend.txt into a caps-locked version and write it to girlfriendcaps.txt:

import System.IO

import Data.Char

main = do

contents <- readFile "girlfriend.txt"

writeFile "girlfriendcaps.txt" (map toUpper contents)

The appendFile function has the same type signature as writeFile and acts almost the same way. The only difference is that appendFile doesn’t truncate the file to zero length if it already exists. Instead, it appends stuff to the end of that file.

To-Do Lists

Let’s put the appendFile function to use by making a program that adds a task to a text file that lists stuff that we have to do. We’ll assume that the file is named todo.txt and that it contains one task per line. Our program will take a line from the standard input and add it to our to-do list:

import System.IO

main = do

todoItem <- getLine

appendFile "todo.txt" (todoItem ++ "\n")

Notice that we added the "\n" to the end of each line, because getLine doesn’t give us a newline character at the end.

Save the file as appendtodo.hs, compile it, and then run it a few times and give it some to-do items.

$ ./appendtodo

Iron the dishes

$ ./appendtodo

Dust the dog

$ ./appendtodo

Take salad out of the oven

$ cat todo.txt

Iron the dishes

Dust the dog

Take salad out of the oven

Note

cat is a program on Unix-type systems that can be used to print text files to the terminal. On Windows systems, you can use your favorite text editor to see what’s inside todo.txt at any given time.

Deleting Items


We already made a program to add a new item to our to-do list in todo.txt. Now let’s make a program to remove an item. We’ll use a few new functions from System.Directory and one new function from System.IO, which will all be explained after the code listing.

import System.IO

import System.Directory

import Data.List

main = do

contents <- readFile "todo.txt"

let todoTasks

Return Main Page Previous Page Next Page

®Online Book Reader