Output

Dear Computer

Chapter 7: Immutability and I/O

Output

With Haskell's do notation, we can read input, write output, generate random numbers, and perform any other activity that produces new state. To make a standalone program that has the side effect of printing output, we define main as a do block of print statements:

Haskell
main = do
  putStr "Goodbye"
  putChar ','
  putChar ' '
  putStrLn "Pluto!"

Each of the put* functions returns an altered environment that gets passed along to the next function in the sequence. But we don't see any of this alteration happening. The do syntax makes it implicit. This state-passing mechanism is implemented via an abstraction called a monad, which we will not discuss in further detail.

Put this source code in a file named main.hs and then run it with this command in the shell:

Shell
runhaskell main.hs

This command compiles the script on the fly and then runs the executable. If we wish to build a standalone executable, then we must explicitly compile the program with ghc:

Shell
ghc main.hs
./main

Consider the type signatures of the three common output functions putChar, putStr, and putStrLn, as reported by ghci:

GHCI
> :t putChar
putChar :: Char -> IO ()
> :t putStr
putStr :: String -> IO ()
> :t putStrLn
putStrLn :: String -> IO ()

Some parts of these signatures should seem familiar. The arrows mean that these are functions. The parameter types show that the functions must be passed a Char or String. But then there's the mysterious return type: IO (), which we'll learn more about soon.

There is no putInt or putDouble or putList. If we want to print something that is not a Char or String, we must first turn it into text. The polymorphic show function turns a value into a String:

Haskell
main = do
  putStrLn (show [1..10])

But check out the type signature of function print:

GHCI
> :t show
print :: Show a => a -> IO ()

The print function accepts a parameter of any type that implements the Show typeclass. It calls show for us and prints the result on its own line. This call is equivalent to but much simpler than the earlier putStrLn:

Haskell
main = do
  print [1..10]
← Random Number GeneratorInput →