15 Stream processing and incremental I/O

 

This chapter covers

  • Shortcomings of imperative IO
  • Transformation using stream transducers
  • Building an extensible Process type
  • Single input and output processing with Source and Sink
  • Combining multiple input streams using Tee

We said in the introduction to part 4 that functional programming is a complete paradigm. Every imaginable program can be expressed functionally, including programs that interact with the external world. But it would be disappointing if the IO type were the only way to construct such programs. IO and ST work by simply embedding an imperative programming language into the purely functional subset of features that we have explored up to now. While programming within the IO monad, we have to reason about our programs much like we would in ordinary imperative programming.

We can do better. In this chapter, we show how to recover the high-level compositional style developed in parts 1–3 of this book, even for programs that interact with the outside world. The design space in this area is enormous, and our goal here is not to explore it in its entirety but just to convey ideas and give a sense of what’s possible.

15.1 Problems with imperative I/O: An example

15.2 Transforming streams with simple transducers

15.2.1 Combinators for building stream transducers

15.2.2 Combining multiple transducers by appending and composing

15.2.3 Stream transducers for file processing

15.3 An extensible process type for protocol parameterization

15.3.1 Sources for stream emission

15.3.2 Ensuring resource safety in stream transducers

15.3.3 Applying transducers to a single-input stream

15.3.4 Multiple input streams

15.3.5 Sinks for output processing

15.3.6 Hiding effects in effectful channels

15.3.7 Dynamic resource allocation