IO is the type used to describe Haskell computations that interact with the world outside pure functions. An action such as main :: IO () may perform effects while yielding unit, (), when no meaningful result is needed. Creating an action does not itself perform the interaction; evaluation realizes it. section 3.1 section 3.1.1
Use do notation to sequence actions and pass produced values onward. In a do block, <- evaluates an action and binds its result; the final expression determines the action’s type. putStrLn is a function that produces an IO action, while getLine itself has type IO String. section 3.1.1 section 3.5
Listing 3.1 A simple program that reads a line from the user and prints it
module Main (main) where #1 main :: IO () main = do #2 line <- getLine #3 putStrLn line #4
A minimal interactive program reads a line, binds it with <-, and prints it as the final IO () action. section 3.1.1
Keep effects at the boundary of a program:
- Read arguments, files, and user input in IO actions; print results through actions. section 3.2.2
- Put parsing, numbering, filtering, formatting, and other transformations in pure functions. section 3.2.2
- Call pure functions from actions to transform values before output, reducing impure code and making logic easier to reason about and test. section 3.2.1
- Let pure code choose an action when needed: a Maybe result can select either a help-printing action or an action built from a file path. section 3.4
Number input lines until a blank line
A recursive function can take a counter and return IO (). It reads a line, stops with return () when the line is empty, or prints the numbered line and calls itself with counter + 1. Both branches of the conditional must produce actions of the same type. Here, return wraps a value in IO; it does not exit an action early. section 3.1.2 section 3.1.3
IO is also a monad. do notation is syntactic sugar usable with monads generally, though its monadic details can be deferred while writing basic programs. The Monad interface permits values to be brought into a monadic context with return and sequenced with bind; it deliberately does not provide a general way to extract an IO value into pure code. section 12.1.5 section 12.1.6
Interactions with files, networks, and processes can fail. IO failures may involve exceptions, whereas optional or failed pure computations can be represented with Maybe or Either when their cases are handled directly. section 14.3.3





