Next: Polymorphic functions
Up: Procedural abstraction using higher-order
Previous: Procedural abstraction using higher-order
  Contents
Functions as input parameters
Consider the following problems for computing three different sums.
- Computing the sum of all integers from
to
(Example 3.12).
A functional algorithm for the problem can be given in terms
of a function
as
- Computing the sum of squares of all integers from
to
. A
functional algorithm for the problem can be given in terms
of the function
as
- Computing the sum of a sequence of terms in the following series
which converges to
:5.5
A
functional algorithm for the problem can be given in terms
of the function
as
Clearly, the three algorithms share a lot in common; so much so that they
warrant the design of a common function which combines the common characteristics
of the three different different functions. This can be achieved by
defining a generic summation whose functionality is given by
i.e., the summation of an arbitrary function
in the range
in
steps defined by the successor function
. In order to write a
functional algorithm for such a generic summation one needs to be able
to accept two functions
and
as input in addition to the parameters
and
which belong to the set
. Here
may be any
generic type on which the operation
is defined (e.g.
or
).
Hence, the generic
summation must be a higher-order function whose type is
A functional algorithm for the generic summation can then be given as
The advantage of defining such a higher-order function independent of
any particular problem is that the analysis of correctness and efficiency of
the algorithm can be carried out in a general setting.
Exercise 5.13
For the function
- Establish the correctness assuming the
correctness of the functions
and
. Note that
and
are just procedural abstractions of two unknown functions.
- Determine the time and the space complexity
in terms of number of calls to the functions
and
.
summation.nw01In ML the higher-order summation function can be written as
follows:
2summation
fun summation(a:int,b,f,succ) =
if (a > b) then
0
else
f(a) + summation(succ(a),b,f,succ);
> val summation = fn : int * int * (int -> int) * (int -> int) -> int
3
Then the summation functions
and
of the type
can be defined in terms
of the higher-order summation function as follows:
4sum
fun sum(a,b) =
let
fun term(x) = x : int;
fun next(x) = x + 1
in
summation(a,b,term,next)
end;
> val sum = fn : int * int -> int
5sum_squares
fun sum_squares(a,b) =
let
fun term(x) = x*x : int;
fun next(x) = x + 1
in
summation(a,b,term,next)
end;
> val sum_squares = fn : int * int -> int
6
The functions
and
are of the type
. In contrast, the
function
is of the type
.
In order to satisfy the strict type checking in ML , we have to
re-define the function
so that it returns a value
of the type
.
7real_summation
fun real_summation(a : int,b,f,succ) =
if (a > b) then
0.0
else
f(a) + summation(succ(a),b,f,succ);
> val real_summation = fn : int * int * (int -> real) * (int -> int) -> real
8
Note that the only change in code that is required is the
replacement of the identity element of summation. We can now
define
as
9pi_sum
fun pi_sum(n) =
let
fun term(x) = 1.0/real(x*(x+2));
fun next(x) = x + 4
in
summation(1,n,term,next)*8.0
end;
> val pi_sum = fn : int * int -> real
10
Thus we see that the same form of the abstract function
can be used to compute sums of various different kinds.
It may appear that the same effect may be achieved by defining the
summation function directly (not as a higher-order function) as
11summation (incorrect)
fun summation(a,b) =
if (a > b) then
0
else
f(a)+summation(succ(a),b);
> Error: unbound variable or constructor: succ, f
12
and by defining a particular summing function, say sum as
13sum (incorrect)
fun sum(a:int,b:int) =
let
fun f(x : int) = x;
fun succ(x) = x + 1
in
summation(a,b)
end;
14
However, this will not work because the functions f and succ
are local to the function sum and are not defined in the global
scope of the function summation.
Both f and succ are free parameters in the scope of the function
summation and in order to evaluate the function summation these
two functions must be defined in its global scope with the same names.
It is not advisable to define the function summation with f
and succ as free parameters because then, in order to use the
function summation, one has to look inside its definition
to find these names and it cannot be used as a black-box. In principle
this would be similar to having to open the back panel of a TV
with a screw-driver in order to determine whether it has 110V or
220V power input. Clearly, then the TV ceases to be a black-box (at least
figuratively speaking).
Next: Polymorphic functions
Up: Procedural abstraction using higher-order
Previous: Procedural abstraction using higher-order
  Contents
Subhashis Banerjee
2003-08-02