Standard ML is a functional programming language, and it is more than that. Functional programs have many virtues. They are concise, secure and elegant. They are easier to understand and easier to prove correct than imperative programs.
Functional--or applicative--languages relieve the programmer of many of the difficulties which regrettably occupy much of the attention of a programmer working in imperative--or procedural--languages. These difficulties range from implementing re-usable routines to conserving and managing memory to mastering the representation of data values. Some of these have attendant responsibilities. Once programmers understand how values are represented in memory they must subsequently ensure that they are inspected and updated in a manner which is consistent with that representation. Even after the difficulties of managing the machine's primary memory have been comprehended, there are still the difficulties of transferring data from primary memory to secondary memory and the complications of disk access mechanisms and input/output libraries.
A functional programmer can transcend these matters. Applicative languages have secure polymorphic type systems which simplify the task of writing re-usable, general-purpose routines. Applicative programmers delegate the task of memory management to ``garbage collection'' routines which need only be written once for the implementation of the language; not every time that another program is written in the language. Applicative languages hide the machine representation of data, making it impossible to write programs which are sensitive to the byte order of the underlying machine or to introduce other unintended dependencies. Using disk input routines can be avoided because of the interactive nature of applicative languages which allows data to be entered with the minimum of fuss. Using disk output routines can be avoided by allowing the user to export the environment bindings as easily as checkpointing a database. Of course any realistic programming language must offer input and output routines for disk, screen and keyboard but their use can be avoided for many applicative programming problems.
Functional languages do have shortcomings. It might be said that some programming problems appear to be inherently state-based. The uniformity of representation which applicative programming languages offer then becomes a handicap. Although an applicative solution to such a problem would be possible it might have an obscure or unnatural encoding. Another possible worry is that the functional implementation might be inefficient when compared with a straightforward imperative one. This would be a shame; a programming language should not make it difficult for a programmer to write efficient programs.
Imperative programming languages also have their strengths. They often provide explicit support for the construction of programs on a large scale by offering simple, robust modules which allow a large programming task to be decomposed into self-contained units to be implemented in isolation. If these units are carefully crafted and general they may be included in a library, facilitating their re-use in other programs. Modules also enable programs to be efficiently recompiled by avoiding the need to recompile parts of the program which have not changed. By adding high-level constructs to an imperative language one can elevate the practice of programming. The only reason not to provide high-level constructs in the language itself is that optimisations can sometimes be made if a programmer tailors every instance of a general high-level routine to take account of the particular idiosyncracies of the programming task at hand. Where is the profit in this? One is often only exchanging a saving in a relatively cheap resource, such as memory, for an increased amount of an expensive service, that of application programmer time. The present state of programming is that well-designed modern imperative languages such as Java [AG96] come close to offering the type security and programming convenience which functional programming languages offered in the 1970's. The interest in and increasing adoption of this language should be viewed as an encouraging, if slow, shift away from the miserliness which has bedevilled programming practice since the inception of the profession.
Is there a way to combine the virtues of well-designed applicative programming languages with the virtues of well-designed imperative ones? Of course, the resulting language might never become the world's most frequently used programming language. Perhaps programming simply is not a virtuous activity or perhaps the resulting language would be a hideous mutant; sterile and useless for programming. We think that computer scientists should feel that they have a moral duty to investigate the combination of the best of these two kinds of programming languages. In this author's opinion, the Standard ML programming language provides the most carefully designed and constructed attempt so far to develop a language to promote the relative virtues embodied in well-designed applicative and imperative programming languages.