Online Book Reader

Home Category

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

By Root 537 0
use the bracketOnError function from Control.Exception. It’s very similar to bracket, but whereas the bracket will acquire a resource and then make sure that some cleanup always gets done after we’ve used it, bracketOnError performs the cleanup only if an exception has been raised. Here’s the code:

import System.IO

import System.Directory

import Data.List

import Control.Exception

main = do

contents <- readFile "todo.txt"

let todoTasks = lines contents

numberedTasks = zipWith (\n line -> show n ++ " - " ++ line)

[0..] todoTasks

putStrLn "These are your TO-DO items:"

mapM_ putStrLn numberedTasks

putStrLn "Which one do you want to delete?"

numberString <- getLine

let number = read numberString

newTodoItems = unlines $ delete (todoTasks !! number) todoTasks

bracketOnError (openTempFile "." "temp")

(\(tempName, tempHandle) -> do

hClose tempHandle

removeFile tempName)

(\(tempName, tempHandle) -> do

hPutStr tempHandle newTodoItems

hClose tempHandle

removeFile "todo.txt"

renameFile tempName "todo.txt")

Instead of just using openTempFile normally, we use it with bracketOnError. Next, we write what we want to happen if an error occurs; that is, we want to close the temporary handle and remove the temporary file. Finally, we write what we want to do with the temporary file while things are going well, and these lines are the same as they were before. We write the new items, close the temporary handle, remove our current file, and rename the temporary file.

Command-Line Arguments

Dealing with command-line arguments is pretty much a necessity if you want to make a script or application that runs on a terminal. Luckily, Haskell’s standard library has a nice way of getting command-line arguments for a program.

In the previous section, we made one program for adding an item to our to-do list and one program for removing an item. A problem with them is that we just hardcoded the name of our to-do file. We decided that the file will be named todo.txt and that users will never have a need for managing several to-do lists.

One solution is to always ask the users which file they want to use as their to-do list. We used that approach when we wanted to know which item to delete. It works, but it’s not the ideal solution because it requires the users to run the program, wait for the program to ask them something, and then give the program some input. That’s called an interactive program.

The difficult bit with interactive command-line programs is this: What if you want to automate the execution of that program, as with a script? It’s harder to make a script that interacts with a program than a script that just calls one or more programs. That’s why we sometimes want users to tell a program what they want when they run the program, instead of having the program ask the user once it’s running. And what better way to have the users tell the program what they want it to do when they run it than via command-line arguments?

The System.Environment module has two cool I/O actions that are useful for getting command-line arguments: getArgs and getProgName. getArgs has a type of getArgs :: IO [String] and is an I/O action that will get the arguments that the program was run with and yield a list of those arguments. getProgName has a type of getProgName :: IO String and is an I/O action that yields the program name. Here’s a small program that demonstrates how these two work:

import System.Environment

import Data.List

main = do

args <- getArgs

progName <- getProgName

putStrLn "The arguments are:"

mapM putStrLn args

putStrLn "The program name is:"

putStrLn progName

First, we bind the command-line arguments to args and program name to progName. Next, we use putStrLn to print all the program’s arguments and then the name of the program itself. Let’s compile this as arg-test and try it out:

$ ./arg-test first second w00t "multi word arg"

The arguments are:

first

second

w00t

multi word arg

The program name is:

arg-test

More Fun with To-Do Lists

In the previous examples, we made one program for adding

Return Main Page Previous Page Next Page

®Online Book Reader