The material is grouped into three parts. In the first, we build a foundation, focusing on programming over basic types and lists, using first-order, non-polymorphic programs. Only when readers are fluent with the basics of functions, types and program construction do we look at the twin ideas of higher-order functions and polymorphism, which together give modern functional programming its distinctive flavour and power. Based on this, in the final part we look at larger-scale programming, supported also by an exploration of user-defined types, modules and lazy evaluation, and concluding with an analysis of program efficiency.

As we saw above, we can write down calculations of expressions which use our defined functions, and also give proofs of various of their properties; both aspects are emphasised in the text (although it can be read independently of the material on proof).

The crucial test of any programming text is whether it helps the reader to write
programs. The book is called `The *Craft* of Functional Programming'
because it aims to give readers help with design of programs right from the start. At
each stage we give advice on how functions, types or modules can be designed; in
many cases we give a series of steps which aim to simplify the problem by breaking
it down into simpler parts.

Software of any importance will be modified during its lifetime; modification and re-use are emphasised when we discuss design, and in the final part of the book we look in particular at how libraries of polymorphic higher-order functions can be re-used in many different contexts.

The advice on design is supplemented by examples and case studies of varying size and complexity. Some, like the Huffman coding example, are free-standing; others, such as the library database, are re-visited a number of times to illustrate how new techniques can be applied to solve existing problems in different ways. This is important in linking together the different parts of the text, and in showing the variety of ways that any problem can be solved in Miranda.

Finally, other case studies are introduced step-by-step. We first see the simulation example when we design algebraic data types in Chapter 9; next it provides realistic examples of abstract data types in Chapter 11, and finally we look at its top level in Chapter 13. Each aspect is separate; together they provide a substantial case study. Other aspects of our approach are

- Throughout the text, whenever a function is defined we give its type explicitly; the type forms the first and most important piece of documentation for any definition.
- Material is included on how to find proofs by induction; a template to help with setting down the precise goals of an induction proof is included, as is a discussion of how to search for proofs about functions defined by equations.
- Appendices contain support material of various kinds. Common errors and error messages are collected in one; a glossary of programming terms commonly used in another. A third appendix lists a major part of the Miranda standard environment, a fourth examines how functional and imperative programming are linked and a fifth gives references for further reading. Finally, we give an overview of how to understand an unfamiliar function definition in Miranda.
- Over four hundred exercises of varying difficulty are included.
- Further support material which is be found on these World Wide Web pages.