Resources from the chapter notes on the book Introduction to Functional Programming using Haskell, second edition. Note that it is a 1998 book, so not everything said might be entirely up-to-date. Nonetheless, the resources should still be relevant. Most of the text explanations are taken verbatim from the chapter notes on the book, adding links to the resources whenever available. If it's a freely available paper or book, there is a link to it, otherwise it's just the resource's name.
For further information about the denotational aspects of programming languages, consult Stoy (1977) or Gordon (1979). The implementation of lazy functional languages is covered in Peyton Jones(1987) and Peyton Jones and Lester (1991). The formal derivation of programs from their specifications is the subject of Morgan (1996) and Kaldewaij (1990), although the target programming language is procedural, not functional. For functional and relational treatment of program derivation in categorical setting, consult Bird and de Moor (1997). This is and advanced text, suitable for those particularly interested in the mathematics of programming, and can be studied after the present one.
Modern accounts of boolean algebra and logic, suitable for computing
scientists, include Ben-Ari (1993),
Burke and Foxley (1996),
Gries and Schneider (1995).
The theoretical foundations of type classes are studied in
Wadler and Blott (1989)
and Jones (1992,
1995).
The notations f x g and f + g are used in a branch of mathematics
called category theory, which from one point of view can be regarded as a
foundation for functional programming. Suitable texts for computing scientists
include Barr and Wells (1995),
Pierce (1991),
Bird and de Moor (1997).
A full discussion of computer arithmetic can be found in Knuth (1981). Linear and binary search are fundamental programming techniques and are covered in Morgan (1996) and Kaldewaij (1990). The properties of floors, as well as many other useful numerical functions, are given in Graham, Knuth, and Patashnik (1990). Church numerals are presented in Church (1941) and discussed in Gordon (1994).
A great deal of work has been done on automatic or machine-aided generation of
induction proofs; see, for example, Boyer and Moore (1979),
Gordon, Milner, and Wadsworth (1979),
Paulson (1983),
Martin and Nipkow (1990).
The relationship between polymorphic functions and naturality conditions is
explored in Wadler (1989);
see also Bird and de Moor (1997).
The fusion laws for fold operators were systematised in
Malcolm (1990),
Fokkinga (1992),
Jeuring (1993),
and Meijer (1992).
The maximum segment sum problem is described in
Bentley (1987).
The derivation recorded in this chapter was first given in
Bird (1989, Algebraic Identities for Program Calculation).
Good source books on trees include Cormen, Leiserson, and Rivest (1990) and Knuth (1973b). Rose trees, which also go under the name general trees, were so named in [Meertens (1987)](#Meertens. Lambert Meertens. First steps towards the theory of rose trees. CWI, Amsterdam; IFIP Working Group 2.1 working paper 592 ROM-25, 1988). Gibbons' thesis (1991) contains a systematic treatment of a number of algorithms on trees.
Huffman coding was described in Huffman (1952; A Method for the Construction of Minimum-Redundancy Codes); see also Hu (1982) and Knuth (1973a). Thompson (1996) also gives a functional program for Huffman coding.
The problem of computing Meertens' number was first considered in Bird (1991). Gödel numbering was used by Gödel in his 1931 proof of his famous theorem on the incompletness of arithmetic; see the collected works: Gödel (1990). Popular accounts of the importance of this result on twentieth-century thought are given in Hofstadter (1979) and Penrose (1994).
Published in: Journal of Functional Programming, Volume 8 Issue 1, January 1998, Pages 83 - 88
For more information on lazy evaluation and grah reduction, consult the books
Peyton Jones (1987)
and Peyton Jones and Lester (1991).
Asymptotic notation and the solution of recurrence relations using O-notation
is covered in Cormen et al (1990).
The subject of aysmptotic timing analyses of lazy functional programs is still
a research area; for various approaches to the problem, see
[Bjerner and Holmström (1989)](#A composition approach to time analysis of first order lazy functional programs),
Sands (1995, A Naïve Time Analysis and its Theory of Cost Equivalence),
and Wadler (1987).
The idea of fusing two computations is as old as the subject of program
transformation itself; for an early reference on the technique in a functional
setting, see Burstall and Darlington (1997).
The accumulating parameter technique is studied in
Bird (1984).
For more on the tupling strategy of program optimisation, see
Bird (1980) and
Pettrossi (1984).
The principle of optimality, and its importance to dynamic programming
algorithms (of which the paragraph problem is an example), is discussed in most
books on algorithm design; see Bellman (1957; Dynamic Programming)
where the technique was first discussed, and also
de Moor (1994)
which presents the ideas in a categorical setting.
Bird and de Moor (1997)
contains a systematic account of the use of dynamic programming in solving
optimisation problems. The problem of filling a paragraph is treated in
Bird (1986)
and in Knuth and Plass (1981; Breaking paragraphs into lines).
The idea of eliminating intermediate datatypes from a computation is studied in
Wadler (1984; Listlessness is better than laziness. PhD thesis;,
1990b);
see also Bird and de Moor (1997)
for other examples.
Quicksort is due to Hoare (1962).
Hughes (1984)
was the first to notice the space leak in quicksort when expressed as a
functional program. See
Runciman and Röjemo (1996)
for techniques for identifying space leaks.
The algebraic specification of abstract datatypes is described in
Guttag and Horning (1987, The algebraic specification of abstract data types).
Two useful source texts on datatypes and their specification
are Martin (1986, Data Types and Data Structures)
and Harrison (1989, abstract data types in modula-2).
Amortised complexity is described in
Cormen et al. (1990)
and, in a functional setting, in
Schoenmakers (1992)
and Okasaki (1996).
The original presentation of AVL trees can be found in
Adelson-Velski and Landis (1962);
see also Knuth (1973b).
There are many other balanced tree schemes; for example,
Cormen et al. (1990)
discusses red-black trees, and
Andersson (1993)
a simple scheme based on two operations, skew and split.
The simple implementation of flexible arrays is described in
Dielissen and Kaldewaji (1995);
see also Hoogerwoord (1991).
The fast queue implementations can be found in
Okasaki (1995).
Okasaki (1996)
contains a wealth of additional material on purely functional data structures.
Originally a Ph.D thesis, later expanded into a book.
Domain theory grew out of the work of Dana Scott in the late 1960s, see Scott (1976) and Scott (1982). An accessible account of the basic mathematics is given in Davey and Priestly (1990); see also Gunter (1992) for a modern treatment of domains and their importance in the semantics of programming languages. Sijtsma's thesis (1988) studies various aspects of infinite-list programs, and gives a number of techniques for reasoning about infinite lists. One chapter is devoted to proof of fairness in the paper-rock-scissors game. Gordon's thesis (1993) contains a useful history of the various approaches to the treatment of interaction in a functional setting. One of the most exciting recent develpments in programming semantics has been the use of games and strategies to provide a model for interactive processes. See the chapters by S. Abramsky and M. Hyland in Pitts and Dyber (1997) for readable accounts of the basic ideas.
Moggi (1989, 1991) introduced monads to computing science as a way of structuring denotational semantics. Independently, Spivey (1990) noted that monads provided a useful way of structuring exception handling in functional programs. Subsequently, Wadler (1990a, 1995) proposed monads as a general technique for structuring functional programs.
Monads are used to structure the Glasgow Haskell compiler, which itself is written in Haskell; see Hall, Hammond, Partain, Jones, and Wadler (1992). Each phase of the compiler uses a monad for bookkeeping information. For instance, the type checker uses a monad that combines state (to maintain a current substitution), a name supply (for fresh type variable names), and exceptions. Monads for interaction have been extended to include concurrency; see Jones, Gordon, and Finne (1996). Monad transformers are discussed in Liang, Hudak, and Jones (1995).
The program for the game of Hangman was adapted from a similar program in Hutton and Meijer (1996).
The special do notation was suggested by Launchbury (1993) and was first implemented by Jones (1993) in a version of Gofer. Subsequently, it was adopted in Haskell.
For a general introduction to practical parsing techniques, and their application in compiler design, consult Aho, Sethi, and Ullman (1986). The design of functional parsers has been a favourite application of functional programming ofr many years, e.g. Burge (1975), Wadler (1985). Modern treatments include Fokker (1995), Hutton (1992), and Hutton and Meijer (1996), on which this chapter is closely based. The converse problem to parsing is pretty printing, the laying out of a structured document in an aesthetically pleasing manner. See Hughes (1995 pretty printing) for a design for a pretty-printing library.
Mike Spivey's original calculator was written in Orwell, a predecessor of Haskell; although the program hasn't been documented in the literature, Spivey (1990) contains a discussion on matching and rewriting expressions. Another interactive equational reasoning assistant for Orwell, called ERA, is described in Wilson (1993). Mechanical theorem proving and interactive proof assistance form a large and buoyant subject, and dozens of systems are available to the interested user. We will not attempt to enumerate them, but the references in Chapter 4 five some pointers. For an easily accessible reference, consult Paulson (1996). This text describes the implementation in ML of a tactical theorem prover called Hal.
The hidden agenda of this chapter was to demonstrate the advantages of phrasing laws and proofs as equations between functional expressions. The mathematical foundations of this approach is the subject matter of category theory (see the references cited in Chapter 2). However, for a truly viable method of specification and proof, one needs to replace functional expressions by relational ones, and equational reasoning by inequational reasoning. See Bird and de Moor (1997) for details.