Previous Contents Next

Similar functional languages

There are several languages similar to Objective CAML, whether through the functional aspect, or through typing. Objective CAML is descended from the ML family, and thus it has cousins of which the closest are across the Atlantic and across the channel in the lineage of SML (Standard ML). The Lisp family, and in particular the Scheme language, differs from ML mainly by its dynamic typing. Two lazy languages, Miranda and Haskell, take up or extend ML's typing in the framework of delayed evaluation. Two functional languages, Erlang and SCOL, developed by the Ericsson and Cryo-Networks corporations respectively, are directed towards communication.

ML family

The ML family comprises two main branches: Caml (Categorical Abstract Machine Language) and its derivatives Caml-Light and Objective CAML, SML (Standard ML) and its descendants SML/NJ and mosml. Caml, the ancestor, was developed between 1986 and 1990 by INRIA's FORMEL project in collaboration with University Paris 7 and the École Normale Supérieure. Its implementation was based on Le_Lisp's runtime. It integrated within the language the definition of grammars and pretty-printers, which allowed communication of values between the language described and Caml. Its type system was more restrictive for mutable values, insofar as it did not allow such values to be polymorphic. Its first descendant, Caml-Light, no longer used the CAM machine, but instead used Zinc for its implementation. The name was nevertheless retained to show its ancestry. It contributed a more lightweight implementation while optimizing the allocation of closures and using an optimizing GC as a precursor to the actual GC. This streamlining allowed it to be used on the PC's of the time. The various Caml-Light versions evolved towards actual typing of imperative features and were enriched with numerous libraries. The following offshoot, Caml Special Light or CSL, introduced parameterized modules and a native-code compiler. Finally the baby is actually Objective CAML which mainly adds the object-oriented extension to CSL. Since there has never been a complete specification of the Caml languages, these various changes have been able to take place in complete freedom.

The SML approach has been the opposite. The formal specification [MTH97] was given before the first implementation. It is difficult to read, and a second book gives a commentary ([MT91]) on it. This method, specification then implementation, has allowed the development of several implementations, of which the best-known is SML/NJ (Standard ML of New Jersey) from Lucent (ex-AT&T). Since its origin, SML has integrated parameterized modules. Its initial type system was different from that of Caml for imperative features, introducing a level of weakness for type variables. The differences between the two languages are detailed in [CKL96]. These differences are being effaced with time. The two families have the same type system for the functional and imperative core, Objective CAML now has parameterized modules. SML has also undergone changes, bringing it closer to Objective CAML, such as for record types. If the two languages don't merge, this mainly derives from their separate development. It is to be noted that there is a commercial development environment for SML, MLWorks, from Harlequin:

Link


http://www.harlequin.com/products/
An SML implementation, mosml, based on Caml-Light's runtime, has also been implemented.

Scheme

The Scheme language (1975) is a dialect of the Lisp language (1960). It has been standardized (IEEE Std 1178-1990). It is a functional language with strict evaluation, equipped with imperative features, dynamically typed. Its syntax is regular and particular about the use of parentheses. The principal data structure is the dotted pair (equivalent to an ML pair) with which possibly heterogeneous lists are constructed. The main loop of a Scheme toplevel is written (print (eval (read))). The read function reads standard input and constructs a Scheme expression. The eval function evaluates the constructed expression and the print function prints the result. Scheme has a very useful macro-expansion system which, in association with the eval function, permits the easy construction of language extensions. It not only supports interrupting computation (exceptions) but also resuming computation thanks to continuations. A continuation corresponds to a point of computation. The special form call_cc launches a computation with the possibility of resuming this one at the level of the current continuation, that is to say of returning to this computation. There are many Scheme implementations. It is even used as a macro language for the GIMP image manipulation software. Scheme is an excellent experimental laboratory for the implementation of new sequential or parallel programming concepts (thanks to continuations).

Languages with delayed evaluation

In contrast with ML or Lisp, languages with delayed evaluation do not compute the parameters of function calls when they are passed, but when evaluation of the body of the function requires it. There is a ``lazy'' version of ML called Lazy ML but the main representatives of this language family are Miranda and Haskell.

Miranda

Miranda([Tur85]) is a pure functional language. That is to say, without side effects. A Miranda program is a sequence of equations defining functions and data structures.

Link


http://www.engin.umd.umich.edu/CIS/course.des/cis400/miranda/miranda.html


For example the fib function is defined in this way:
 
 fib a = 1, a=0 
       = 1, a=1 
       = fib(a-1) + fib(a-2), a>1
Equations are chosen either through guards (conditional expressions) as above, or by pattern-matching as in the example below:
fib 0 = 1
fib 1 = 1
fib a = fib(a-1)+ fib(a-2)
These two methods can be mixed.

Functions are higher order and can be partially evaluated. Evaluation is lazy, no subexpression is computed until the moment when its value becomes necessary. Thus, Miranda lists are naturally streams.

Miranda has a concise syntax for infinite structures (lists, sets): [1..] represents the list of all the natural numbers. The list of values of the Fibonacci function is written briefly: fibs = [a | (a,b) <- (1,1),(b,a+b)..]. Since values are only computed when used, the declaration of fibs costs nothing.

Miranda is strongly typed, using a Hindley-Milner type system. Its type discipline is essentially the same as ML's. It accepts the definition of data by the user.

Miranda is the archetype of pure lazy functional languages.

Haskell

The main Haskell language website contains reports of the definition of the language and its libraries, as well as its main implementations.

Link


http://www.haskell.org


Several books are dedicated to functional programming in Haskell, one of the most recent is [Tho99].

This is a language which incorporates almost all of the new concepts of functional languages. It is pure (without side effects), lazy (not strict), equipped with an ad hoc polymorphism (for overloading) as well as parametric polymorphism à la ML.

Ad hoc polymorphism
This system is different from the polymorphism seen up to now. In ML a polymorphic function disregards its polymorphic arguments. The treatment is identical for all types. In Haskell it is the opposite. A polymorphic function may have a different behavior according to the type of its polymorphic arguments. This allows function overloading.

The basic idea is to define type classes which group together sets of overloaded functions. A class declaration defines a new class and the operations which it permits. A (class) instance declaration indicates that a certain type is an instance of some class. It includes the definition of the overloaded operations of this class for this type.

For example the Num class has the following declaration:
class Num a where
  (+)    :: a -> a -> a
  negate :: a -> a
Now an instance Int of the class Num can be declared in this way:
instance Num Int where
  x + y    =  addInt x y
  negate x = negateInt x
And the instance Float:
instance Num Float where
  x + y    =  addFloat x y
  negate x = negateFloat x
The application of negate Num will have a different behavior if the argument is an instance of Int or Float.

The other advantage of classes derives from inheritance between classes. The descendant class recovers the functions declared by its ancestor. Its instances can modify their behavior.

Other characteristics
The other characteristics of the Haskell language are mainly the following: In fact it contains just about all the high-strung features born of research in the functional language domain. This is its advantage and its disadvantage.

Communication languages

ERLANG

ERLANG is a dynamically typed functional language for concurrent programming. It was developed by the Ericsson corporation in the context of telecommunications applications. It is now open source. The main site for accessing the language is the following:

Link


http://www.erlang.org
It was conceived so that the creation of processes and their communication might be easy. Communications take place by message passing and they can be submitted with delays. It is easy to define protocols via ports. Each process possesses its own definition dictionary. Error management uses an exception mechanism and signals can propagate among processes. Numerous telephony applications have been developed in Erlang, yielding non-negligible savings of development time.

SCOL

The SCOL language is a communication language for constructing 3D worlds. It was developed by the Cryo Networks corporation:

Link


http://www.cryo-networks.com
Its core is close to that of Caml: it is functional, statically typed, parametrically polymorphic with type inference. It is ``multimedia'' thanks to its API's for sound, 2D, and 3D. The 3D engine is very efficient. SCOL's originality comes from communication between virtual machines by means of channels. A channel is an (environment, network link) pair. The link is a (TCP or UDP) socket.

SCOL's originality lies in having resolved simply the problem of securing downloaded code: only the text of programs circulates on the network. The receiving machine types the passed program, then executes it, guaranteeing that the code produced does indeed come from an official compiler. To implement such a solution, without sacrificing speed of transmission and reception, the choice of a statically typed functional language was imposed by the conciseness of source code which it supports.


Previous Contents Next