To Learn More
The principal consequences of adding imperative traits to a functional
language are:
-
To determine the evaluation strategy (strict evaluation);
- to add implementation constraints, especially for the GC (see
Chapter 9);
- For statically typed languages, to make their type system more
complex;
- To offer different styles of programming in the same language,
permitting us to program in the style appropriate to the
algorithm at hand, or possibly in a mixed style.
This last point is important in Objective CAML where we need the same
parametric polymorphism for functions written in either style. For
this, certain purely functional programs are no longer typable after
the addition. Wright's article ([Wri95]) explains the
difficulties of polymorphism in languages with imperative aspects.
Objective CAML adopts the solution that he advocates. The classification of
different kinds of polymorphism in the presence of physical
modification is described well in the thesis of Emmanuel Engel
([Eng98]).
These consequences make the job of programming a bit harder, and
learning the language a bit more difficult. But because the
language is richer for this reason and above all offers the choice of
style, the game is worth the candle. For example, strict evaluation is
the rule, but it is possible to implement basic mechanisms for lazy
evaluation, thanks to the mixture of the two styles. Most purely
functional languages use a lazy evaluation style. Among languages
close to ML, we would mention Miranda, LazyML, and
Haskell. The first two are used at universities for teaching and
research. By contrast, there are significant applications written in
Haskell. The absence of controllable side effects necessitates an
additional abstraction for input/output called monads. One can
read works on Haskell (such as [Tho99]) to learn more about
this subject. Streams are a good example of the mixture of functional
and imperative styles. Their use in lexical and syntactic analysis is
described in Chapter 11.