Generally speaking, modularity in programming means to organize programs in a modular fashion so that they each can be constructed in a relatively isolated manner and then be combined to function coherently. I will introduce in this section some features in ATS that are largely designed to facilitate program organization.
The code employed for illustration in this chapter plus some additional code for testing is available on-line.
The interface for a function or value specifies a type that any implementation of the function or value should possess. For instance, the following code defines a function fact for computing the factorial numbers:
A function interface can be considered as a form of specification. For instance, the above interface for fact specifies that fact is a function that takes one integer argument and returns an integer value. What is so special about this form of specification is that it is formally enforced in ATS through typechecking: Any implementation of fact in ATS must possess the interface declared for it. Of course, this is not a precise specification for fact as there are (infinite) many functions that can be given the same interface. This kind of imprecision can, however, be reduced or even eliminated, sometimes. After dependent types are introduced, I will present an interface for fact such that any implementation of the interface is guaranteed to implement precisely the factorial function as is defined by the following two equations:
fact(0) = 1
fact(n) = n * fact (n-1) for each natural number n > 0
An implementation for fact as the following one can be given at any point where the declared interface for fact is accessible:
As an example of an interface for a value, fact10 is declared as follows to be a value of the type int:
As another example, the following code declares an interface for a polymorphic function named swap_boxed:
It is a standard practice for a programmer to first design interfaces for the functions to be supported in a package before actually implementing any of these functions. When such interfaces are available, application programs can be constructed to check whether the interface design makes sense or is convenient for practical use. Please remember that a superb implementation of a poor design cannot make the design any better. Therefore, testing a design before actually implementing it is often of vital importance. This is especially true if the involved design is complex.