Functors

The Functor type class provides an fmap function for types which implement it. fmap is like a generalised form of map for lists.

class Functor f where
    fmap :: (a -> b) -> f a -> f b

The Functor instance for Maybe is

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

Laws

The functor type class has three laws. Laws are rules that implementing types should follow but are not enforced by the compiler.

  1. The mapping must be structure preserving. This means the output should be the same "shape" as the input.

  2. Identity law - fmap id == id.

  3. Distributivity over (.) - fmap (a . b) == fmap a . fmap b.

Environment functor

(->) is the type level operator. It can be partially applied. ((->) Int) represents all functions which take one argument of type Int. This has kind * -> * so can have a Functor instance.

The functor instance for ((->) e) is called the environment functor. It represents values that exist with respect to some input environment of type e.

instance Functor ((->) e) where
    fmap :: (a -> b) -> (e -> a) -> (e -> b)
    fmap f func = \x -> f (func x)
    -- or equivalently
    fmap = (.)

Control and data functors

Functors can be split into two groups: control and data functors. Data functors are those which store values, such as [] or Maybe. Control functors are used for control flow. An example is the environment functor.

Applicative functors

Applicative functors are a subclass of functors which have the ability to lift values in. This basically mean take a value and put it in a functor without using the constructor. It defines two new functions, pure and (<*>). The first takes a value and lifts it into a functor, the second is the apply function, which applies a lifted function to a lifted value.

class Functor f => Applicative f where
    pure :: a -> f a
    (<*>) :: f (a -> b) -> f a -> f b

The applicative functor instance for Maybe is as follows:

instance Applicative Maybe where
    pure x = Just x
    Just f <*> Just x = Just (f x)
    _      <*> _      = Nothing

Function application function comparison

Functions, functors and applicative functors all have function application functions. Note that <$> is the same as fmap.

($)   ::                    (a -> b) ->   a ->   b
(<$>) :: Functor f     =>   (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b

All three are fairly similar, they take a function in some form, a value in some form and apply the function to the value giving a result in some form. The difference between ($) and (<$>) is that the input and output are wrapped in a functor and then the difference between (<$>) and (<*>) is the function is also wrapped in the functor.