Generalizing by Parameterizing

How can we generalize this example?

One obvious idea is to make the start and stop indices into parameters. We'll neaten up the function a little while we're at it:

Now, what if we wanted to do something similar, but using the fact function instead of the fib function?

Functions as Parameters

Solution: abstract with respect to the fib function.

Note that the first argument of funcs_p_to_q is (automatically) given the polymorphic type int->'a, which is tied to the output type (int *'a) list. So we can also write something like this:

Choosing a parameterization

We could also have chosen a more general parameterization that doesn't force the output to be a list of pairs:

Now we can get the effect of the original function by passing a more complicated function as parameter:

Or use an anonymous function:

Higher-order mapping functions

Higher-order functions are great for operating on entire lists ``at once'':

Function map applies a function to each member of a list and returns the resulting list.

A variant of map is a function that applies a binary function to corresponding elements of two lists:

Higher-order functions with predicates

Function filter applies a predicate (a function that returns a bool) to each member of a list and returns a list containing just the matching members.

Function forall takes a predicate and a list and returns true iff the predicate is true of every member. Note the ``short-circuiting.'' exists can be defined similarly.

List Reduction

Recall these examples:

We can now see how to generalize these functions to a common higher-order function.

Both operate over lists, working from the right (tail) end, calculating a result.

At each list item, the result is calculated by applying a binary combining function f (here + or `^`) to the list item and the result previously calculated for the tail.

A special seed value s (here 0 or "") is needed to start off the computation at the tail of the list.

List Reduction (Continued)

Abstracting over the binary function and the seed value, we get the following function:

If the list has contents then we are computing

If we wrote the list using a prefix form of ``cons'' it would look like this:

Note that we can view reduce(f,s,l) as the result of replacing cons with f and nil with s.

Name that reduce!

Notice that the type of reduce is actually more general than we needed for these examples: the computed value and the list elements do not need to be of the same type:

A surprising number of functions can be written as instances of reduce,e.g.:

Andrew P. Tolmach
Thu Apr 17 14:21:55 PDT 1997