|
|
|
Polymorphic ADTs: Functors and templates
We have previously seen C++ function templates and ML polymorphic
functions -- both are instances of parametric polymorphism.
This idea can be extended to abstract data types: one ADT can take another
ADT as a parameter. In C++ the template mechanism extends to class templates.
The C++ Standard Template Library (STL) uses this to implement various
container classes.
template <class T> class classname {
code including declarations involving type T
}
STL containers include lists, queues, deques, vectors and maps (like python dicts
or perl hashes). Each container template contains code for accessors, often in the
form of iterators but also simple indexing operations. STL template classes
also include algorithms for doing common things with each container type, for example
sorting the contents of a container. For example if vector is declared like this:
template <type T> class vector { }
You can declare a vector of ints like this:
vector<int> v
The vector type includes methods for comparison, subsripting,
assignment, etc. so v can be used as if it were an array. However, it is
imbued with the additional ability to grow as needed when elements are added -- something
that basic C/C++ arrays cannot do.
Polymorphic abstraction in ML: functors
The term functor as used in ML is derived from a branch of mathematics
called category theory. The meaning is entirely different from the use of the word
functor to describe function objects in the C++ world. More on those in a moment.
Suppose we have declarations like this in an ML program
functor F(s : S) = struct
type pair = s.t * s.t
val p : pair = (s.x, s.x)
end
structure S1 = struct
type t = int
val x = 3
end
structure S2 = struct
type t = string list
val x = ["hi", "there"]
end
signature S = sig
type t
val x : t
end
Then we can use F(S1) to mean a structure that looks like
struct
type pair = int*int
val pair = (3,3)
end
while F(S2) means
struct
type pair = string list * string list
val pair = (["hi", "there"], ["hi", "there"])
end
The Standard ML library uses functors extensively to implement its
collection of container classes, just as STL uses C++ templates to implement
its container classes.
The other use of the word functor: function objects in C++
In C++ an object having an operator(...) method is called a
function object or sometimes a functor. The same technique
is frequently useful in Java (because Java has no function pointers if you want to
pass behavior into a method you have to pass an object -- which can have
a method (i.e. a function) as a component. This is a little cleaner in
C++ because you don't have to choose a method name for this purpose -- it should
always be operator in the declaration and then you can just
use the object name itself as a function name when you want to call it.
Hopefully and example will help make this clearer.
class biggerthanX {
private int lx;
public biggerthanX( int x ) {
lx = x;
}
public boolean operator (int y) {
return (y > lx);
}
}
biggerthanX gt4 = new biggerthanX(4);
if (gt4(z)) { /* the operator(int y) method of gt4 is used here */
...
}
|