# Functors

**Functors** generalise the idea of **function mapping** on a data structure type, i.e. applying a function to each element in the data structure. We have looked at the `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:

```haskell
class Functor f where
  fmap :: (a -> b) -> f a -> f b
  (<$) :: a -> f b -> f a
  
  -- Minimal complete definition:
  -- fmap
```

{% hint style="info" %}
The `(<$)` function simply replaces all elements in the data structure with the given value `a.`
{% endhint %}

Comparing `fmap` to `map`:

```haskell
map :: (a -> b) -> [a] -> [b]
```

We can see that `fmap` has the exact same type signature as `map` - but`map` is limited to the type of `lists`, whereas `fmap` can be used with any parameterised type that uses a *type constructor*`f`, i.e. is a class of `Functor f`. Note that the 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 the list type.

Since the `map` and `fmap` functions perform the same action, it is very simple to make the `list` type into a functor (and it is made into one by default) by using the \`instance\` keyword:

```haskell
instance Functor [] where
    -- fmap :: (a -> b) -> [] a -> [] b
    fmap = map
```

However, when it comes to other data structure types, we have to define the `fmap`  function ourselves. For example, the [`Maybe` type](https://wiki.haskell.org/Maybe) (also an instance of the `Functor` class by default) can be made an instance of the `Functor` class as:

```haskell
instance Functor Maybe where
    -- fmap :: (a -> b) -> Maybe a -> Maybe b
    fmap _ Nothing = Nothing
    fmap f (Just x) = Just (f x)
```

In the case of a `Nothing`, we ignore the function and return `Nothing` as `Nothing` generally represents an error state that we 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, i.e. the function application `f x`.

Now let's see how we can make a newly-defined data type into an instance of the `Functor` class. We will first define a data type `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 our case, a node with `0` children will be a `Leaf` that stores some value, and a node with `2` children will be a `Branch` that branches into two new nodes without storing a value itself:

```haskell
data Tree a = Leaf a | Branch (Tree a) (Tree a)
    deriving (Show)
```

And now, we want to make `Tree` a functor, so we have to define the `fmap` function for it:

```haskell
instance Functor Tree where
    -- fmap :: (a -> b) -> Tree a -> Tree b
    fmap f (Leaf x) = Leaf (f x)
    fmap f (Branch l r) = Branch (fmap f l) (fmap f r) 
```

The first case of `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.

To represent the following binary tree:

![Example binary tree.](/files/-MXSCF91qRYstPnEBDzZ)

We can use the following code and `fmap` over the entire data structure, applying the specified function (in this case `(/2)`) to each leaf:

```haskell
ghci> myTree = (Branch (Branch (Leaf 1) (Leaf 2)) (Branch (Leaf 10) (Leaf 20)))
ghci> fmap (/2) myTree

Branch (Branch (Leaf 0.5) (Leaf 1.0)) (Branch (Leaf 5.0) (Leaf 10.0))
```

Note that the `Prelude` comes with an [infix operator](/defining-functions-working-with-functions/the-infix-operator.md) for `fmap` as well - `(<$>)`, not to be confused with the [function application operator](/defining-functions-working-with-functions/function-operators.md), `($)`:

```haskell
 ($)  :: (a -> b) -> a -> b
 
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<$>) = fmap
```

`($)` is the simple function application operator we learned about before, while `(<$>)` is *also a function application operator* but with lifting over a Functor. We could also write the above code as:

```haskell
ghci> myTree = (Branch (Branch (Leaf 1) (Leaf 2)) (Branch (Leaf 10) (Leaf 20)))
ghci> (/2) <$> myTree

Branch (Branch (Leaf 0.5) (Leaf 1.0)) (Branch (Leaf 5.0) (Leaf 10.0))
```

## Functor Laws

There are two functor laws that must be satisfied to ensure that `fmap` works as intended:

```haskell
fmap id = id
```

The `id` is the identity function, and it is 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.

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

The second functor law ensures that *function* *composition* is preserved when using `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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://haskell.hpmeducation.com/functors-applicatives-and-monads/functors.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
