# Functors

## Variance of Functors

This is a summary of this post and this post.

When we look a `Function`'s definition, we see that it is higher-kinded by two, that is, two types need to be defined before we can have a concrete type:

``````foreign import data Function :: Type -> Type -> Type

infix ? Function as ->

-- Rather than writing `Function input output`
-- we write `input -> output`
no_sugar :: Function Input Output

syntax_sugar :: Input -> Output

generic_on_input :: forall a. a -> Output

generic_on_output :: forall b. Input -> b

generic_on_both :: forall a b. a -> b
``````

A type can be a `Functor` if it is higher-kinded by one. In the below example, we specify its input type and leave the output type to be defined in `map`:

``````                   -- (input ->)
instance Functor (Function input) where
-- (input -> a)     -> (input -> b)
map :: forall a b. (a -> b) -> Function input a -> Function input b
map aToB inputToA = (\input -> aToB (inputToA input))
``````

However, what if we specified the output type of `Function` in the instance head and left the input type to be defined in `map`? If so, it would look like this:

``````type FlippedFunc output input = (input -> output)
-- (-> output)
instance Functor (FlippedFunc output) where
-- (a -> output)        -> (b -> output)
map :: forall a b. (a -> b) -> FlippedFunc output a -> FlippedFunc output b
map inputA_To_InputB inputA_To_Output = -- this isn't possible to implement!
``````

We cannot define an instance of `Functor` in this way because the first argument in `map` changes an `a` value to a `b` value. However, if we flipped the direction of the arrow, we could write the function's body:

``````type FlippedFunc output input = (input -> output)

-- (-> output)
instance SomethingElse (FlippedFunc output) where
-- (a -> output)        -> (b -> output)
map_ish :: forall a b. (b -> a) -> FlippedFunc output a -> FlippedFunc output b
map_ish inputB_To_InputA inputA_To_Output =
(\inputB -> inputA_To_Output (inputB_To_InputA inputB))
``````

The above type class is called `Contravariant` and `map_ish` is called `cmap`.

### Functor Re-examined

The above two type classes, `Functor` and `Contravariant`, are the same except for the direction of the arrow in the `map`/`cmap`'s first function argument. The former is called `Functor` instead of `Covariant` because it appears more often than the latter.

Real NamePurescript NameFrequency of AppearanceUsage
Covariant FunctorFunctorVery frequentChanges the output of a function
Contravariant FunctorContravariantInfrequentChanges the input of a function

### Positive and Negative Position

However, there are actually special names for the input and output types:

Positive position: the type variable is the result/output/range/codomain of the function Negative position: the type variable is the argument/input/domain of the function

Or to put it into meta-language: `negativePosition -> positivePosition`

These terms are used so that one can ultimately determine whether a given type is a Covariant or Contravariant Functor by the rules of multplication:

| position 1 | position 2 | end position | + | + | + | | - | - | + | | - | + | - | | + | - | - |

To understand how this works in practice, see Contravariant Functors are Weird

## The 2+ Different Functors

As explained in `../Variance of Functors.md`, there are two different kinds of `Functor`s: covariant Functors and contravariant Functors.

However, one also hears about `Bifunctor`, `Profunctor`, and `Invariant`. These are just different ways of combining those different kinds of functors together:

NameType Class' function nameMeaning
Functor`map`/ `<\$>`/`<#>`Maps 1 type with a Covariant Functor
Contravariant`cmap`/`>\$<`/`>#<`Maps 1 type with a Contravariant Functor
Bifunctor`bimap`
• 1st Type: Covariant map (e.g. `map`)
• 2nd Type: Covariant map (e.g. `map`)
Profunctor`dimap`
• 1st Type: Contravariant map (e.g. `cmap`)
• 2nd Type: Covariant map (e.g. `map`)
Invariant`imap`Maps 1 type with either/both a Covariant Functor or/and a Contravariant Functor