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.: