# Functor

A simple intuition for Functor is to see Functor as some kind of container and the ability to apply some function f to every element in the container without altering it's structure.

As an example, a list is a container of elements and we can apply a function to each element in the list without changing it's underlying structure.

There are many kinds of functor. Here we will explore

- Covariant functor (fmap)
- Contravariant functor (contramap)
- Invariant/Exponential functor (xmap)
- Bifunctor
- Profunctor

## Covariant functor

This might also be thought of as the canonical Functor implementation.

Given a function of (a -> b) and a functor of a return a functor of b

```
class CovariantFunctor f where
fmap :: (a -> b) -> f a -> f b
instance CovariantFunctor Maybe where
fmap _ Nothing = Nothing
fmap f (Just x) = Just (f x)
instance CovariantFunctor [] where
fmap f [] = []
fmap f (x:xs) = f x : fmap f xs
instance CovariantFunctor IO where
fmap f x = x >>= return . f
```

Instances of the covariant functor should satisy two laws

```
fmap id == id
fmap (f . g) = fmap f . fmap g
```

## Contravariant functor

Somtimes referred to as a cofunctor