Online Book Reader

Home Category

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

By Root 407 0
Create the following file and save it as words.txt.

dogaroo

radar

rotor

madam

This is what we get by redirecting it into our program:

$ ./palindrome < words.txt

not a palindrome

palindrome

palindrome

palindrome

Again, we get the same output as if we had run our program and put in the words ourselves at the standard input. We just don’t see the input that our program gets because that input came from the file.

So now you see how lazy I/O works and how we can use it to our advantage. You can just think in terms of what the output is supposed to be for some given input and write a function to do that transformation. In lazy I/O, nothing is eaten from the input until it absolutely must be, because what we want to print right now depends on that input.

Reading and Writing Files

So far, we’ve worked with I/O by printing stuff to the terminal and reading from it. But what about reading and writing files? Well, in a way, we’ve already been doing that.

One way to think about reading from the terminal is that it’s like reading from a (somewhat special) file. The same goes for writing to the terminal— it’s kind of like writing to a file. We can call these two files stdout and stdin, meaning standard output and standard input, respectively. Writing to and reading from files is very much like writing to the standard output and reading from the standard input.

We’ll start off with a really simple program that opens a file called girlfriend.txt, which contains a verse from Avril Lavigne’s hit song “Girlfriend,” and just prints out to the terminal. Here’s girlfriend.txt:

Hey! Hey! You! You!

I don't like your girlfriend!

No way! No way!

I think you need a new one!

And here’s our program:

import System.IO

main = do

handle <- openFile "girlfriend.txt" ReadMode

contents <- hGetContents handle

putStr contents

hClose handle

If we compile and run it, we get the expected result:

$ ./girlfriend

Hey! Hey! You! You!

I don't like your girlfriend!

No way! No way!

I think you need a new one!

Let’s go over this line by line. The first line is just four exclamations, to get our attention. In the second line, Avril tells us that she doesn’t like our current partner of the female persuasion. The third line serves to emphasize that disapproval, and the fourth line suggests we should go about finding a suitable replacement.

Let’s also go over the program line by line. Our program is several I/O actions glued together with a do block. In the first line of the do block is a new function called openFile. It has the following type signature:

openFile :: FilePath -> IOMode -> IO Handle

openFile takes a file path and an IOMode and returns an I/O action that will open a file and yield the file’s associated handle as its result. FilePath is just a type synonym for String, defined as follows:

type FilePath = String

IOMode is a type that’s defined like this:

data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode

Just like our type that represents the seven possible values for the days of the week, this type is an enumeration that represents what we want to do with our opened file. Notice that this type is IOMode and not IO Mode. IO Mode would be the type of I/O action that yields a value of some type Mode as its result. IOMode is just a simple enumeration.

Finally, openFile returns an I/O action that will open the specified file in the specified mode. If we bind that action’s result to something, we get a Handle, which represents where our file is. We’ll use that handle so we know which file to read from.

In the next line, we have a function called hGetContents. It takes a Handle, so it knows which file to get the contents from, and returns an IO String—an I/O action that holds contents of the file as its result. This function is pretty much like getContents. The only difference is that getContents will automatically read from the standard input (that is, from the terminal), whereas hGetContents takes a file handle that tells it which file to read from. In all other respects, they work the same.

Just like

Return Main Page Previous Page Next Page

®Online Book Reader