tobold.org

correct • elegant • free

△ How to do IO in Haskell △

◅ return is not control-flow syntax

Summary of the do expression ▻

Actions versus computations

By now, you might be starting to smell a rat: is there really much difference between "IO actions" and "IO computations"? Well, no.

IO actions do return a value, just not a very interesting one, as you can see in putstr.hs.

main = do
  x <- putStr "putStr returns the value "
  print x

The output of this program is always putStr returns the value ().

Conversely, you don't have to bind the value returned by an IO computation. Suppose we define printn that writes some output and also returns a count of how many characters it wrote (a bit like printf() and friends in C), in printn.hs.

printn x =
    let out = show x
    in do
      putStr out
      return (length out)

main = do
  c <- printn [0..9]
  printn (" has " ++ show c ++ " characters")

In the first call, we bind the value returned by printn to the name c; in the second call we simply ignore it.

So forget IO computations; we will use the term IO action henceforth, whether the action returns a useful value or not. Of course, you need to take account of whether an IO action returns a value that you want to capture by binding it with <-.

In practice, the functions defined by the Haskell Report all seem to fall into one category or the other: either they do something (write some output, change current directory, etc.) and return IO (), or they retrieve a value and return it (read some input, report current directory, etc.). It is probably wise to follow this style and avoid creating functions like printn.

△ How to do IO in Haskell △

◅ return is not control-flow syntax

Summary of the do expression ▻