Let’s say we have a value: 5.

We know how to apply a function to this value:

(* 2) 5

would equal 10.

In Haskell, values can have a context.

For now, let’s think of that context as a box, like so:

Functors

A functor can apply a function to a value inside a box.

To do this, the typeclass of Functor defines the function fmap.

fmap :: (a -> b) -> f a -> f b

We can derive quite a bit from the type:

The first argument is a function that takes type a and returns type b.

The second argument can be read as a box with a value of type a inside.

It returns a box with a value of type b

Under the hood, fmap will apply this function to the value inside the box, and returns the result inside a new box.

Here’s a visual example:

fmap extracts the value 5 from this box, applies the function show to it, and returns the result in a new box.

In this particular case, the type declaration for fmap becomes

fmap :: (Int -> String) -> f Int -> f String

Awesome!

Now that we have an intuitive understanding of functors, let’s have a look at a real world example. Cue the Maybe type.

data Maybe a = Just a | Nothing

Maybe is implemented as functor like this:

instance Functor Maybe where

fmap f Nothing = Nothing

fmap f (Just x) = Just (f x)

Let’s break this down.

When fmap matches the second argument as Nothing, it will simply return Nothing again. After all, you can’t apply a function to nothing ;)

However, if it matches (Just x), it will apply the function on x and return the result, wrapped in Just.

You can think of Maybe as the box around the values in our first example.

When we substitute the box out for Maybe, we get:

Maybe replaces the box of the first example.

applying any function on Nothing yields Nothing

While we’re at it, let’s take a closer look at the functor implementation for a type you already know.

instance Functor [] where

fmap = map

That’s right, lists are functors too! fmap is simply defined as the pre-existing function map. Chances are you’ve encountered the map function before; it simply applies the function to every item of the list and returns a list with the results:

That’s it! That’s really all there is to functors.

In part 2 and 3, I will cover applicatives and monads, and try to explain how they are all related. Read part 2 here.