logo
 
Polymorphic ADTs and two kinds of Functor
CptS 355 - Programming Language Design
Washington State University
Home
Calendar
Syllabus
Resources
People
Project turn-in

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 */
      ...
   }

                                                                                                                                                                                                                                                                                                                                             
  (c) 2003 Curtis Dyreson, (c) 2004, 2005 Carl H. Hauser           E-mail questions or comments to Prof. Carl Hauser