Functor

Functor is an abstract concept. Some concrete exercises will give something to grasp while you think about it.

A functor is an abstract concept, so we will begin with some examples.

In order to have an example to work with, define the function:

f :: Double -> Double
f x = x*x

If you want to apply f to a single number, no problem.

ghci> x = 10
ghci> f x
100

What if you want to apply f to a bunch of numbers?

ghci> xs = [10,20,30]

You probably know about map.

ghci> map f xs
[100,400,900]

The function fmap does the same thing in this case.

ghci> fmap f xs
[100,400,900]

What would it mean to apply f to a Maybe Double? With an input of Just 10, it would make the most sense for f to output Just 100. With an output of Nothing, the sensible output (from any function) would be Nothing.

That is what fmap is made to do.

ghci> mx = Just 10
ghci> fmap f mx
Just 100
ghci> nx = Nothing
ghci> fmap f nx
Nothing

Haskell allows you create an fmap function for your own data types by making them instances of the Functor class. The definition of fmap for Maybe looks like this:

instance Functor Maybe where
    fmap f (Just x) = Just (f x)
    fmap f (Nothing) = Nothing

As you can see, it specifies how fmap f acts on all of the possibilities for input.

Exercises (not copied from lecture)

Use the Data Types page for the definitions used below.

Important note about functors: fmap is only supposed to operate on the last type

  1. Write the instance declaration to make Triple an instance of Functor.

     data Triple a = Never | Unlikely a | Surely a
    
  2. Write the instance declaration to make Twin (below) an instance of Functor.

     data TwinL a = NotPresent | TwinR a a
    
  3. Make Yikes a Functor.

     data YikesL a b = YikesR a a b
    
  4. A binary tree

     data Tree a = Leaf a |
                   Tree {getValue :: a,
                         getLeft  :: (Tree a),
                         getRight :: (Tree a)}
    
    1. Make an example of a tree with only one value.
    2. Make an example of a tree with three values (one on the left, one on the right).
    3. Make Tree into a Functor.