map
function that does exactly that but is limited to a specific data structure - list
. However, any parameterised type (data structure) can be made into an instance of the functor
class so that it supports function mapping to its elements through the use of the fmap
function:(<$)
function simply replaces all elements in the data structure with the given value a.
fmap
to map
:fmap
has the exact same type signature as map
- butmap
is limited to the type of lists
, whereas fmap
can be used with any parameterised type that uses a type constructorf
. Note that form of[a]
and [b]
is just syntax sugar for the list type and is equivalent to [] a
and [] b
, where []
is the type constructor for lists.map
and fmap
function perform the same action, it is very simple to make the list
type into a functor (and it is made into one by default):fmap
function ourselves. For example, the Maybe type (also an instance of the Functor class by default) and can be made an instance as:Nothing
, we ignore the function and just return Nothing
as Nothing
in general represents an error state that we then want to propagate through our fmap
function as well. Otherwise, we apply the function f
to the underlying value x
of Just x
and return the Maybe type (using the Just
constructor) of the result.Tree
that will represent a full binary tree (https://en.wikipedia.org/wiki/Binary_tree). A full binary tree is a binary tree type in which every tree node has either 0
or 2
children. In the case of a node with 0
children, it will be a Leaf
that stores some value, and in the case of a node with 2
children, it will be a Branch
that branches into two new nodes:Tree
a functor, so we have to define the fmap
function for it:Leaf
is analogous to how we defined the Just
case of the Maybe
functor - we apply the function f
to the underlying value x
and return it wrapped in the Leaf
constructor. In the other case, where we are dealing with a Branch
we recursively apply fmap
to both children nodes of the branch.fmap
over the entire data structure, applying the passed function to each leaf:Prelude
comes with an infix operator for fmap
as well - (<gt;)
:($)
is the simple function application operator we learned about before, while (<gt;)
is also a function application operator but with lifting over a Functor. We could also write the above code as:fmap
works as intended:id
is the identity function, and it used to simply return the unaltered argument passed in. This means that mapping the id
function over a structure should return the same structure back unaltered.fmap
so that it does not matter whether we map a composed function (g . f)
or map the first function g
and then the second function f
, as long as the order of the g
and f
functions stays the same.