views:

1801

answers:

11

I've come across the term 'Functor' a few times while reading various articles on functional programming, but the authors typically assume the reader already understands the term. Looking around on the web has provided either excessively technical descriptions (see the Wikipedia article) or incredibly vague descriptions (see the section on Functors at the ocaml-tutorial website).

Can someone kindly define the term, explain its use, and perhaps provide an example of how Functors are created and used?

Edit: While I am interested in the theory behind the term, I am less interested in the theory than I am in the implementation and practical use of the concept.

Edit 2: Looks like there is some cross-terminoligy going on: I'm specifically referring to the Functors of functional programming, not the function objects of C++.

+7  A: 

In OCaml, it's a parameterised module.

If you know C++, think of an OCaml functor as a template. C++ only has class templates, and functors work at the module scale.

An example of functor is Map.Make; module StringMap = Map.Make (String);; builds a map module that works with String-keyed maps.

You couldn't achieve something like StringMap with just polymorphism; you need to make some assumptions on the keys. The String module contains the operations (comparison, etc) on a totally ordered string type, and the functor will link against the operations the String module contains. You could do something similar with object-oriented programming, but you'd have method indirection overhead.

Tobu
Um, C++ has functors.
Kornel Kisielewicz
I got that from the ocaml website - but I don't understand what the use of a parameterized module would be.
Erik Forbes
@Kornel Yeah, what I described is an OCaml concept. The other concept is just “functional value”, which is nothing particular in FP.@Erik I expanded slightly, but the reference docs are slow to load.
Tobu
I think I'm beginning to see.
Erik Forbes
+3  A: 

Here's an article on functors from a programming POV, followed up by more specifically how they surface in programming languages.

The practical use of a functor is in a monad, and you can find many tutorials on monads if you look for that.

Craig Stuntz
now my brain hurts.
Alex Brown
You're not alone, Alex. =X
Erik Forbes
A: 

Functor is not specifically related to functional programming. It's just a "pointer" to a function or some kind of object, that can be called as it would be a function.

alemjerus
There is a specific FP concept of a functor (from category theory), but you're right that the same word is also used for other things in non-FP languages.
Craig Stuntz
Are you sure that function pointers are Functors? I don't see how function pointers fulfil the two Functor Laws, especially the Second Functor Law (preservation of morphism composition). Do you have a proof for that? (Just a rough sketch.)
Jörg W Mittag
A: 

Put simply, a functor, or function object, is a class object that can be called just like a function.

In C++:

This is how you write a function

void foo()
{
    cout << "Hello, world! I'm a function!";
}

This is how you write a functor

class FunctorClass
{
    public:
    void operator ()
    {
        cout << "Hello, world! I'm a functor!";
    }
};

Now you can do this:

foo(); //result: Hello, World! I'm a function!

FunctorClass bar;
bar(); //result: Hello, World! I'm a functor!

What makes these so great is that you can keep state in the class - imagine if you wanted to ask a function how many times it has been called. There's no way to do this in a neat, encapsulated way. With a function object, it's just like any other class: you'd have some instance variable that you increment in operator () and some method to inspect that variable, and everything's neat as you please.

Matt
No, those functors aren't the type theory notion that is used by FP languages.
Tobu
I can kind of see how one could prove that `FunctorClass` fulfils the first Functor Law, but could you sketch out a proof for the second Law? I don't quite see it.
Jörg W Mittag
+5  A: 

There is a pretty good example in the O'Reilly OCaml book that's on Inria's website (which as of writing this is unfortunately down). I found a very similar example in this book used by caltech: Introduction to OCaml (pdf link). The relevant section is the chapter on functors (Page 139 in the book, page 149 in the PDF).

In the book they have a functor called MakeSet which creates a data structure that consists of a list, and functions to add an element, determine if an element is in the list, and to find the element. The comparison function that is used to determine if it's in/not in the set has been parametrized (which is what makes MakeSet a functor instead of a module).

They also have a module that implements the comparison function so that it does a case insensitive string compare.

Using the functor and the module that implements the comparison they can create a new module in one line:

module SSet = MakeSet(StringCaseEqual);;

that creates a module for a set data structure that uses case insensitive comparisons. If you wanted to create a set that used case sensitive comparisons then you would just need to implement a new comparison module instead of a new data structure module.

Tobu compared functors to templates in C++ which I think is quite apt.

Niki Yoshiuchi
+1  A: 

Given the other answers and what I'm going to post now, I'd say that it's a rather heavily overloaded word, but anyway...

For a hint regarding the meaning of the word 'functor' in Haskell, ask GHCi:

Prelude> :info Functor
class Functor f where
  fmap :: forall a b. (a -> b) -> f a -> f b
  (GHC.Base.<$) :: forall a b. a -> f b -> f a
        -- Defined in GHC.Base
instance Functor Maybe -- Defined in Data.Maybe
instance Functor [] -- Defined in GHC.Base
instance Functor IO -- Defined in GHC.Base

So, basically, a functor in Haskell is something that can be mapped over. Another way to say it is that a functor is something which can be regarded as a container which can be asked to use a given function to transform the value it contains; thus, for lists, fmap coincides with map, for Maybe, fmap f (Just x) = Just (f x), fmap f Nothing = Nothing etc.

The Functor typeclass subsection and the section on Functors, Applicative Functors and Monoids of Learn You a Haskell for Great Good give some examples of where this particular concept is useful. (A summary: lots of places! :-))

Note that any monad can be treated as a functor, and in fact, as Craig Stuntz points out, the most often used functors tend to be monads... OTOH, it is convenient at times to make a type an instance of the Functor typeclass without going to the trouble of making it a Monad. (E.g. in the case of ZipList from Control.Applicative, mentioned on one of the aforementioned pages.)

Michał Marczyk
+13  A: 

There are three different meanings, not much related!

  • In Ocaml it is a parametrized module. See manual. I think the best way to grok them is by example: (written quickly, might be buggy)

    module type Order = sig
        type t
        val compare: t -> t -> bool
    end;;
    
    
    module Integers = struct
        type t = int
        let compare x y = x > y
    end;;
    
    
    module ReverseOrder = functor (X: Order) -> struct
        type t = X.t
        let compare x y = X.compare y x
    end;;
    
    
    (* We can order reversely *)
    module K = ReverseOrder (Integers);;
    Integers.compare 3 4;;   (* this is false *)
    K.compare 3 4;;          (* this is true *)
    
    
    module LexicographicOrder = functor (X: Order) -> 
      functor (Y: Order) -> struct
        type t = X.t * Y.t
        let compare (a,b) (c,d) = if X.compare a c then true
                             else if X.compare c a then false
                             else Y.compare b d
    end;;
    
    
    (* compare lexicographically *)
    module X = LexicographicOrder (Integers) (Integers);;
    X.compare (2,3) (4,5);;
    
    
    module LinearSearch = functor (X: Order) -> struct
        type t = X.t array
        let find x k = 0 (* some boring code *)
    end;;
    
    
    module BinarySearch = functor (X: Order) -> struct
        type t = X.t array
        let find x k = 0 (* some boring code *)
    end;;
    
    
    (* linear search over arrays of integers *)
    module LS = LinearSearch (Integers);;
    LS.find [|1;2;3] 2;;
    (* binary search over arrays of pairs of integers, 
       sorted lexicographically *)
    module BS = BinarySearch (LexicographicOrder (Integers) (Integers));;
    BS.find [|(2,3);(4,5)|] (2,3);;
    

You can now add quickly many possible orders, ways to form new orders, do a binary or linear search easily over them. Generic programming FTW.

  • In functional programming languages like Haskell, it means some type constructors (parametrized types like lists, sets) that can be "mapped". To be precise, a functor f is equipped with (a -> b) -> (f a -> f b). This has origins in category theory. The Wikipedia article you linked to is this usage.

    class Functor f where
        fmap :: (a -> b) -> (f a -> f b)
    
    
    instance Functor [] where      -- lists are a functor
        fmap = map
    
    
    instance Functor Maybe where   -- Maybe is option in Haskell
        fmap f (Just x) = Just (f x)
        fmap f Nothing = Nothing
    
    
    map (+1) [2,3,4]   -- this is [3,4,5]
    map (+1) (Just 5)  -- this is Just 6
    map (+1) Nothing   -- this is Nothing
    

So, this is a special kind of a type constructors, and has little to do with functors in Ocaml!

  • In imperative languages, it is a pointer to function.
sdcvvc
+57  A: 
Norman Ramsey
This is an excellent answer - thanks a bunch for the information. =)
Erik Forbes
Wish I could upvote this answer more times.
nagnatron
I understand both ML-functors and Haskell-functors, but lack the insight to relate them together. What's the relationship between these two, in a category-theoretical sense?
Wei Hu
@Wei Hu: Category theory has never made any sense to me. The best I can say is that all three notions involve mapping.
Norman Ramsey
According to this Haskell wiki: http://en.wikibooks.org/wiki/Haskell/Category_theory , it's like this:A category is a collection of objects and morphisms (functions), where the morphisms are from objects in a category to other objects in that category. A functor is a function which maps objects and morphisms from one category to objects and morphisms in another. Least that's how I understand it. What that means exactly for programming I have yet to understand.
paul
+2  A: 

Other answers here are complete, but I'll try another explanation of the FP use of functor. Take this as analogy: A functor is a container of type a that, when subjected to a function that maps from a->b, yields a container of type b.

Unlike the abstracted-function-pointer use in C++, here the functor is not the function; rather, it's something that behaves consistently when subjected to a function.

seh
+4  A: 

The best answer to that question is found in "Typeclassopedia" by Brent Yorgey.

This issue of Monad Reader contain a precise definition of what a functor is as well as many definition of other concepts as well as a diagram. (Monoid, Applicative, Monad and other concept are explained and seen in relation to a functor).

http://haskell.org/sitewiki/images/8/85/TMR-Issue13.pdf

excerpt from Typeclassopedia for Functor: "A simple intuition is that a Functor represents a “container” of some sort, along with the ability to apply a function uniformly to every element in the container"

But really the whole typeclassopedia is a highly recommended reading that is surprisingly easy. In a way you can see the typeclass presented there as a parallel to design pattern in object in the sense that they give you a vocabulary for given behavior or capability.

Cheers

JFT
+1  A: 

You got quite a few good answers. I'll pitch in:

A functor, in the mathematical sense, is a special kind of function on an algebra. It is a minimal function which maps an algebra to another algebra. "Minimality" is expressed by the functor laws.

There are two ways to look at this. For example, lists are functors over some type. That is, given an algebra over a type 'a', you can generate a compatible algebra of lists containing things of type 'a'. (For example: the map that takes an element to a singleton list containing it: f(a) = [a]) Again, the notion of compatibility is expressed by the functor laws.

On the other hand, given a functor f "over" a type a, (that is, f a is the result of applying the functor f to the algebra of type a), and function from g: a -> b, we can compute a new functor F = (fmap g) which maps f a to f b. In short, fmap is the part of F that maps "functor parts" to "functor parts", and g is the part of the function that maps "algebra parts" to "algebra parts". It takes a function, a functor, and once complete, it IS a functor too.

It might seem that different languages are using different notions of functors, but they're not. They're merely using functors over different algebras. OCamls has an algebra of modules, and functors over that algebra let you attach new declarations to a module in a "compatible" way.

A Haskell functor is NOT a type class. It is a data type with a free variable which satisfies the type class. If you're willing to dig into the guts of a datatype (with no free variables), you can reinterpret a data type as a functor over an underlying algebra. For example:

data F = F Int

is isomorphic to the class of Ints. So F, as a value constructor, is a function that maps Int to F Int, an equivalent algebra. It is a functor. On the other hand, you don't get fmap for free here. That's what pattern matching is for.

Functors are good for "attaching" things to elements of algebras, in an algebraically compatible way.