A side effect is an interaction with state outside a function, beyond computing its result. Reading a file, printing text, consulting the current time, generating random values, accessing a database, or communicating through a network all depend on or alter something beyond a function’s explicit input. A pure function instead consumes its arguments and produces an output only from them. section 1.2.2 section 1.1.1
This boundary makes code easier to analyze by reading it: a pure function cannot secretly obtain extra data from a file or network, and immutable data avoids values that change over time. Haskell restricts side effects, while providing special programming models for operations that must interact with the outside world. section 1.1.1 section 1.1.2
In Haskell, external interaction is represented with IO actions rather than performed inside ordinary pure functions. `main :: IO ()` is an action, not a conventional function returning a useful value. IO actions can read command-line arguments and files or print to the screen; their results can then be passed into pure transformations. section 3.1 section 3.2
A practical design separates a program into two layers:
- Keep transformations pure when they only process supplied values: parsing an already-provided argument list, numbering lines, filtering lines, and formatting strings. section 3.2.2
- Put resource access in actions: obtain arguments, read a file, and print results. section 3.2.2
- Place reusable, side-effect-free logic in a library module and connect it to IO in an executable module. section 4.4.2
A line-numbering command
A command-line line-numbering tool reads its options and a selected file through IO actions. Its core remains pure: choose a numbering rule, transform `[String]` into numbered lines, and format those lines. The executable composes those results with file reading and screen output. This keeps the main behavior reusable while isolating environmental interaction at the edges. section 3.2 section 3.2.2 section 4.4.2
Figure 3.3 The components and actions of the tool for numbering lines with data flow represented as arrows
Trace how command-line input and file contents enter actions, move through pure line processing, and return to an output action. section 3.2.2
Monads and applicatives help control and compose effectful work while preserving the separation in the type system. IO permits interaction with the environment, but pure functions cannot extract an arbitrary value from a monadic context; doing so would evade the state or effects that context must handle. More elaborate applications can use monad transformers when effectful computations need read-only data, mutable state, and collected output together. section 12.1.6 section 15.0























