Functor on the Typeclassopedia.
Functor is the most fundamental typeclass in the standard libraries. Intuitively, a
Functor can be viewed as a sort of “container,” coupled with an ability to apply a function to every element in the container. One example is a list: this is a container of elements, and we can uniformly apply a function to every element using
Having a single
fmap method means that we don’t have to implement and remember several
map methods for different data structures e.g.
map over lists,
This also enables us to write code that works with any
Functor, simply by invoking
fmap polymorphically. This enables a powerful sort of code reuse.
There are two main intuitions for
Functoris a container, or more precisely, a computational context we can map over. Data structures are the most natural example of this.
fmapis curried, we can write the type signature as
fmap :: (a -> b) -> (f a -> f b). It transforms a “normal” function
g :: a -> binto one that operates over containers
fmap g :: f a -> f b. This transformation is called a lift.
Recalling the familiar pattern of mapping over a list, we can implement an instance of
Functor as follows.
As we’d expect,
fmap works like
ghci> fmap (\x -> x + 2) [1..10] [3,4,5,6,7,8,9,10,11,12] ghci> fmap (*2) [1..10] [2,4,6,8,10,12,14,16,18,20]
Maybe is an instance of functor:
Suppose we have a
Tree data structure defined recursively as follows:
We can write a
Functor instance as follows:
This gives us a function that operates as follows:
There are two laws any
Functor instance must satisfy:
fmap id = id
This just means mapping
id over a container must leave the container unchanged.
fmap (g . f) = fmap g . fmap f
This says that it doesn’t matter whether we map a composed function or first map one and then the other.
Applicative on the Typeclassopedia.