Computing Reviews
Today's Issue Hot Topics Search Browse Recommended My Account Log In
Review Help
Search
Functional programming using standard ML
Wikström Å., Prentice Hall International (UK) Ltd., Hertfordshire, UK, 1987. Type: Book (9789780133319682)
Date Reviewed: May 1 1992
Comparative Review

Functional programming is of growing importance, especially in university computer science programs. In particular, it is taught at most British universities, and a functional programming language is the first language many British students study. In general, the subject has reached a mature point, having two bi-annual conferences, a number of journals, and implementations of a commercial quality.

It is worth reviewing exactly what is meant by functional programming, since this phrase has meant different things at different times. Functional programming involves the definition of data objects, including functions, that can then be evaluated to give results. The definitions are explicit and usually resemble equations, in contrast to the implicit functions defined by commands in imperative languages. Because of this, functional languages tend to be higher-level, giving shorter, more readable code. More important, because the programs are equations, it is easy to see how proofs of correctness can be written: simply infer consequences of the equations given. In a similar way, programs can be transformed from inefficient to more efficient versions.

In the last five years or so, a convergence of ideas has become manifest in the languages Haskell [1], Hope [2], Miranda [3], and Standard ML [4,5] (to name the most important). These languages allow functions to be first class citizens, or in other words, to be passed as arguments to or returned as results by functions. A simple example of such a higher order function is map, which takes a function f as its argument and returns the function that applies f to every member of a list. These languages are strongly and statically typed, with all errors reported before evaluation. This typing is not as restrictive as might first be thought because functions can have polymorphic type, meaning that they may be used over a collection of different types without compromising type security. The map function is an instance of this--the function f can be of any type, the only proviso being that map f is applied to a list of elements of the same type as the domain of f. To support large-scale programming, the languages contain module systems of varying degrees of sophistication.

It would be wrong to think that these languages are all the same. Some, like Standard ML, contain non-functional features like assignment, although many authors lay stress on their functional subsets. A fundamental difference lies in their approach to evaluation. Traditionally, function arguments are evaluated before being passed to the body (the strict evaluation discipline), but this need not be done. Arguments can be evaluated when and as they are needed. If this is done efficiently, evaluation is lazy; lazy languages like Haskell and Miranda allow novel methods of programming using infinite lists and the like.

One language that is clearly not functional in the sense of this review is LISP. The LISP tradition is long and honorable, but quite distinct, as LISP is both weakly typed and used in an inherently imperative way.

Despite the growing interest in functional programming, the number of books on programming in this style is small. Moreover, I find it curious that many of them devote substantial space to discussions of either implementations or the foundations of the subject, such as the lambda calculus; it would be unusual to open a book on imperative programming to find chapters on compiler construction or Turing machines. The books chosen for review here, however, concentrate on programming.

Bailey

Bailey’s introductory text gives a thorough treatment of functional programming in Hope. The book aims to start from scratch, and succeeds, taking the student slowly through topics like the development of simple recursive definitions of functions, which might receive a more rapid treatment in other texts. More novel ideas, such as functions as arguments and functions as results, are treated in the latter half of the book, with an early concentration on more concrete, first-order aspects. This focus has the disadvantage that only on page 187 can the author introduce examples of “true functional programming” in its entirety.

Table 1: Quantitative data
BaileyBird & WadlerHolyerPaulsonReadeSokolowskiWikstrom
Number of pages300300225420600250450
Number of chapters99910141123
Number of exercises1092724930124041232
Solutions to exercisesAllNoneNoneNone50%AllAll
Bibliography (pages)0113104 (annotated)2

Another distinctive feature is the treatment of evaluation--the author gives a number of simulated evaluations that are useful both in creating an insight into this style of programming and in efficiency estimations. A drawback of this operational approach is that nothing is seen of program transformation or verification, which are among the distinctive features of the paradigm. The book also includes a summary of the Hope language.

The main drawback of this text is its lack of larger examples, either in the text itself or in the exercises, which are mainly of the form “write a function to do…” and therefore can give little insight into the software engineering aspects of the topic. Nonetheless, this book is a clear and readable introduction to the basics of functional  programming. 

Bird and Wadler

This text introduces a notation that is close to the Miranda programming language (indeed closer than the appendix discussing the differences suggests, as Miranda has been modified somewhat since publication of the book). It is clearly written and covers all important aspects of lazy functional programming, as well as containing many relevant examples. One of its major advantages is that it is not always looking over its shoulder at the imperative paradigm, comparing approaches--it develops functional programming as a coherent approach to programming in itself.

The authors’ approach is sophisticated: they state that their primary aim is “to convey a view of programming as a mathematical activity,” with mathematical reasoning (about programs) lying at the heart of the subject. In a number of places they emphasize the synthesis of programs from their specifications, using libraries of “laws” to guide their proofs. These methods are complex, and it could be argued that they belong more to a second course in programming than to an introduction. In other situations the authors go from the abstract to the concrete, the most obvious example being the introduction of the recursion operator over lists, foldr, before explicit recursion has been used. Clearly the foldr approach is elegant, but in my experience students only learn to use foldr properly after writing recursive definitions for themselves, moving from the concrete to the abstract.

Some of the highlights of the book come in the examples, which exploit laziness to give strategies for game playing and so forth. The authors also make many perceptive comments on the novel ways in which programs can be modularized in lazy systems.

Despite its more abstract approach, the book can be recommended as a course text that would nicely complement a more concrete approach taken in lectures and classes. Experienced functional programmers can also learn from this book, especially about the elegance and power of the transformational approach.

Holyer

Holyer’s text gives complete coverage of the Miranda programming language and system, including modules and the operating system interface as well as a useful list of Miranda standard definitions. He includes three interesting case studies--a personal notebook, a telephone exchange simulation, and a small expert system--which together show that functional programming is of wider than mathematical applicability. He also gives some good hints on program design and on how imperative and functional programming are related. He carefully explains how expressions are evaluated, which gives a clear insight into the different time and space behaviors of various functions. The final chapters discuss various implementation issues, semantics, and other functional languages. Holyer also provides a Miranda library.

On the other hand, the book has a number of drawbacks. The second chapter is a feature-by-feature account of the language; it contains relatively few examples and exercises to illustrate the features as they are introduced. The reader is forced to wait until the third and later chapters to see anything substantial. Miranda is strongly typed and, as the author points out, can deduce the types of functions without their being specified. Unfortunately, the author seems to see this as a reason to omit types throughout the book, thereby sacrificing clarity for brevity.

Table 2: Qualitative data
BaileyBird & WadlerHolyerPaulsonReadeSokolowskiWikstrom
Prerequisites:
Imperative programming?NoNoSomeYesYesYesNo
Discrete math?NoYesNoYesNoYesNo
LanguagesHopeMirandaMirandaStandard MLMiranda, Standard MLStandard MLStandard ML
ClarityGoodGoodGoodGoodGoodReasonableGood
DifficultyEasierHarderEasierHarderEasierHarderEasier
Depth of coverageIntroductoryFullFullFullFullDeep but patchyIntroductory
Case studies0432 large321

Another omission concerns the logical reading of functional programs and the ease with which programs can be proven to have certain properties: Holyer gives no proofs of correctness. Despite these drawbacks, this book is solid and could certainly be used as a textbook for a functional programming course that uses Miranda.

Paulson

Paulson has written a readable guide to functional programming, which will take the reader through all the features of Standard ML, including exceptions, the module system, and imperative reference types; he also takes pains to explain lazy data structures such as lists. The reader clearly needs previous exposure to programming, and the author adopts a cautious approach to novel ideas--for instance, higher-order functions are introduced relatively late. This approach has the drawback of making some of the earlier examples less elegant than they might be, but the author calls on his teaching experience to justify this delay.

The exposition is cumulative, with two larger and well-presented case studies at the end of the book drawing on most of the material introduced. The book is also strong on program verification, with a detailed presentation of various program proofs and a realistic summary of the strengths and weaknesses of this approach to software development. A useful aspect of this book is the giant exclamation points that signal explanations of various pitfalls in the ML system: these are of great help to students trying to understand why the compiler has produced a particularly incomprehensible error message, for example.

One drawback of this text is the treatment of efficiency. It is discussed throughout, but no tools are provided with which readers can estimate the efficiency of programs they write or see in the book. Syntax charts and predefined idents enhance the book. Finally, the author’s style can be both elegant and caustic.

Reade

Although the notation used here is close to Standard ML, the author’s primary aim is to teach functional programming, so he is happy to add features from other languages, such as list comprehensions and lazy evaluation, when the exposition requires it. The coverage of topics is clear and is supported well by three case studies, two of which are refreshingly nonmathematical in feel: a small graphics package and a “Game of Life” program. Functional languages are often stereotyped as mathematical, so it is good to see examples to the contrary. The author also notes how functional programming techniques can affect programming methodology: printing and processing are completely separate modules in the graphics package, for instance.

Despite treating the elementary parts of the subject at a pace accessible to the beginner, the author manages to treat some complex aspects of functional programming, such as a lazy dictionary akin to a Prolog difference list program and general techniques of continuation-based programming. He also gives thorough coverage of program verification. Perhaps one drawback is the relatively late introduction of lists--this means that when higher-order functions and polymorphism are first discussed, many of the natural examples cannot be introduced. Efficiency is also discussed later than it might be, but this delay is partly because any discussion of efficiency must wait until a formal execution model has been described.

Sokolowski

This book is somewhat eccentric. In the introduction the author states that it is not a handbook, a reference guide, or a beginner’s guide. In fact, he states, “some prior experience with functional programming would also be an advantage.” It can be read as a second course in functional programming, which examines various aspects of this paradigm critically. The author begins with a long discussion of the relationship between functional and imperative programming, and then examines the type system of Standard ML (and implicitly other languages, including Miranda). He points out a number of drawbacks of the type system as it stands, and gives examples of how it might be extended. Finally, he gives a straightforward introduction to the module system before tersely discussing extended examples from the field of implementation.

It would be difficult to recommend this book as a text for a first course, but to someone experienced in functional programming, it provides some interesting insights.

Wikström

The book is intended primarily for beginners, and as such succeeds. It contains enough of the general material found in first courses (what is a computer, what is syntax, and so on) that it could be used as the introductory text in most computing programs. It is based solely on Standard ML and omits the language’s more complex features, such as exceptions, reference types, and modules. The author takes pains to explain new ideas as he introduces them; his treatment of higher-order functions as things that are “partially applicable” is especially clear.

Evaluation is treated formally, through an axiomatic (or structured) operational semantics for the language. This treatment is rigorous and gives the system a sound basis. The only drawback is that the equational aspect of functional programming is treated late, and does not receive the emphasis given in other texts.

A larger example appears at the end of the book. This example is well done, with the only disadvantage being its use of the ML I/O system, which is neither referentially transparent nor simple to understand. Supplementary material includes an early version of the Standard ML language definition and a glossary of functional programming terms.

Comparison

For the complete beginner in computing, both Wikström and Bailey provide gentle introductions to the subject, even if they fail to cover some more advanced material. Bird and Wadler also provide a beginners’ text, but it is suitable only for those who have a strong mathematical background or at least will be happy with a more formal treatment. (Of course, a lecturer does not have to teach only in the style of the textbook used--a more concrete approach could use Bird and Wadler as an adjunct.) The advantage of Bird and Wadler’s book is that they manage to convey some of the distinctive features of functional programming through their approach and examples.

Even though Reade and Paulson both require some background in imperative programming, they write in different yet accessible styles, and either would be most suitable for an early course in functional programming. Reade gives slightly broader coverage of functional programming constructs, and Paulson gives slightly broader coverage of the non-functional aspects of ML, but both cover the basic material and their case studies competently.

Holyer gives broad coverage of Miranda; the order of presentation is a drawback, but lecturers can decide how to use the book. Sokolowski provides an interesting perspective on functional programming, but only as a second course on the subject.

Reviewer:  Simon Thompson Review #: CR115815
1) Hudak, P.; Peyton Jones, S.; and Wadler, P. Report on the functional programming language Haskell, version 1.1. Technical Report, Dept. of Computer Science, Yale University, New Haven, CT, 1991.
2) Burstall, R. M.; MacQueen, D. B.; and Sanella, D. T. HOPE: an experimental applicative language. Technical Report, University of Edinburgh, Edinburgh, Scotland, UK, 1980.
3) Turner, D. A. An overview of Miranda. In Research Topics in Functional Programming, D. A. Turner, Ed., Addison-Wesley, Reading, MA, 1990, 1–16.
4) Milner, R.; Tofte, M.; and Harper, R. The definition of Standard ML. MIT Press, Cambridge, MA, 1990.
5) Milner, R. and Tofte, M. Commentary on Standard ML. MIT Press, Cambridge, MA, 1991.
Comparative Review
This review compares the following items:
  • Functional programming using standard ML:
  • Functional programming with Hope:
  • An introduction to functional programming:
  • Functional programming with Miranda:
  • ML for the working programmer:
  • Elements of functional programming:
  • Applicative high order programming:
  • Bookmark and Share
      Featured Reviewer  
     
    Applicative (Functional) Programming (D.1.1 )
     
     
    Abstract Data Types (D.3.3 ... )
     
     
    Applicative (Functional) Languages (D.3.2 ... )
     
     
    Functional Constructs (F.3.3 ... )
     
     
    Hope (D.3.2 ... )
     
     
    Lists, Stacks, And Queues (E.1 ... )
     
      more  
    Would you recommend this review?
    yes
    no
    Other reviews under "Applicative (Functional) Programming": Date
    Prospects for functional programming in software engineering
    Banâtre J., Jones S., Le Métayer D. (ed), Springer-Verlag New York, Inc., New York, NY, 1991. Type: Book (9780387538525)
    Aug 1 1992
    On the expansion of non-linear functions
    Harrison P. Acta Informatica 28(6): 559-574, 1991. Type: Article
    Oct 1 1992
    Language as an intellectual tool
    McIntyre D. IBM Systems Journal 30(4): 554-581, 1991. Type: Article
    Dec 1 1993
    more...

    E-Mail This Printer-Friendly
    Send Your Comments
    Contact Us
    Reproduction in whole or in part without permission is prohibited.   Copyright 1999-2024 ThinkLoud®
    Terms of Use
    | Privacy Policy