Functor
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
-
Write the instance declaration to make
Triple
an instance ofFunctor
.data Triple a = Never | Unlikely a | Surely a
-
Write the instance declaration to make Twin (below) an instance of
Functor
.data TwinL a = NotPresent | TwinR a a
-
Make
Yikes
aFunctor
.data YikesL a b = YikesR a a b
-
A binary tree
data Tree a = Leaf a | Tree {getValue :: a, getLeft :: (Tree a), getRight :: (Tree a)}
- Make an example of a tree with only one value.
- Make an example of a tree with three values (one on the left, one on the right).
- Make Tree into a Functor.