Functional programming is a complete programming paradigm. All programs imaginable can be expressed functionally, including those that mutate data in place and interact with the external world by writing to files or reading from databases. In this part of the book, we apply what we covered in parts 1–3 to show how functional programming can express these effectful programs.
We begin chapter 13 by examining the most straightforward handling of external effects, using an I/O monad. This provides a simplistic embedded imperative syntax in a functional programming context. We can use the same general approach to handle local effects and mutation, which we introduce in chapter 14. Both of these chapters motivate the development of more composable ways to deal with effects. In chapter 15, our final chapter, we develop a library for streaming I/O and discuss how to write composable and modular programs that incrementally process I/O streams.
Our goal in this part of the book is not to cover absolutely every technique relevant to handling I/O and mutation. Rather, we want to introduce some essential ideas to equip you with a conceptual framework for future learning. You’ll undoubtedly encounter problems that don’t look exactly like those discussed here. But along with parts 1–3, after finishing this part, you’ll be in the best position to apply FP to whatever programming tasks you may face.