This post assumes prior knowledge of - the `Functor`

class / concept - the functor instance for `(->) r`

## Why

Not all higher kinded types `* -> *`

can have a `Functor`

instance. While types like `Maybe a`

, `(x, a)`

, `r -> a`

, `Either e a`

and `[a]`

are `Functors`

in `a`

, there are some types that cannot have a `Functor`

instance. A good example is `Predicate`

:

`newtype Predicate a = Predicate { getPredicate :: a -> Bool }`

We call this type a predicate in `a`

because, given some value of type `a`

we can obtain a `True`

or a `False`

. So, for example: - `Predicate (> 10)`

is a predicate in `Int`

which returns true if the number is greater than 10, - `Predicate (== "hello")`

is a predicate in `String`

which returns true if the string is equal to *"hello"*, and - `Predicate not`

is a predicate in `Bool`

which returns the negation of the boolean value it receives.

We can try writing a `Functor`

instance and see what we can learn:

```
instance Functor Predicate where
fmap :: (a -> b) -> Predicate a -> Predicate b
fmap f (Predicate g) =
Predicate
$ \b -> _welp
```

As the type hole above would suggest, we need to return a `Bool`

value, and we have: - `b :: b`

- `f :: a -> b`

- `g :: a -> Bool`

There is no way we can combine these terms at all, let alone in such a way as to obtain a `Bool`

value. The only way we would be able to obtain a `Bool`

value is by calling `g`

, but for that, we need an `a`

-- but all we have is a `b`

.

What if `f`

was reversed, though? If we had `f' :: b -> a`

, then we could apply `b`

to it `f' b :: a`

and then pass it to `g`

to get a `Bool`

. Let's write this function outside of the `Functor`

class:

```
mapPredicate :: (b -> a) -> Predicate a -> Predicate b
Predicate g) =
mapPredicate f (Predicate
$ \b -> g (f b)
```

This looks very weird, compared to `Functor`

s, right? If you want to go from `Predicate a`

to `Predicate b`

, you need a `b -> a`

function?

*Exercise 1*: fill in the typed hole `_e1`

:

```
greaterThan10 :: Predicate Int
= Predicate (> 10)
greaterThan10
exercise1 :: Predicate String
= mapPredicate _e1 greaterThan10 exercise1
```

*Exercise 2*: write `mapShowable`

for the following type:

```
newtype Showable a = Showable { getShowable :: a -> String }
mapShowable :: (b -> a) -> Showable a -> Showable b
```

*Exercise 3*: Use `mapShowable`

and `showableInt`

to implement `exercise3`

such that `getShowable exercise3 True`

is `"1"`

and `getShowable exercise3 False`

is `"2"`

.

```
showableInt :: Showable Int
= Showable show
showableInt
exercise3 :: Showable Bool
= exercise3
```

## How

`Predicate`

and `Showable`

are very similar, and types like them admit a `Contravariant`

instance. Let's start by looking at it:

```
class Contravariant f where
contramap :: (b -> a) -> f a -> f b
```

The instances for `Predicate`

and `Showable`

are trivial: they are exactly `mapPredicate`

and `mapShowable`

. The difference between `Functor`

and `Contravariant`

is exactly the function they receive: one is "forward" and the other is "backward", and it's all about how the data type is defined.

All `Functor`

types have their type parameter `a`

in what we call a *positive* position. This usually means there can be some `a`

available in the type (which is always the case for tuples, or sometimes the case for `Maybe`

, `Either`

or `[]`

). It can also mean *we can obtain an a*, like is the case for

`r -> a`

. Sure, we need some `r`

to do that, but we are able to obtain an `a`

afterwards.On the opposite side, `Contravariant`

types have their type parameter `a`

in what we call a *negative* position: they *need* to consume an `a`

in order to produce something else (a `Bool`

or a `String`

for our examples).

*Exercise 4*: Look at the following types and decide which can have a `Functor`

instance and which can have a `Contravariant`

instance. Write the instances down:

```
data T0 a = T0 a Int
data T1 a = T1 (a -> Int)
data T2 a = T2L a | T2R Int
data T3 a = T3
data T4 a = T4L a | T4R a
data T5 a = T5L (a -> Int) | T5R (a -> Bool)
```

As with `Functor`

s, we can partially apply higher kinded types to write a `Contravariant`

instance. The most common case is for the flipped version of `->`

:

`newtype Op a b = Op { getOp :: b -> a }`

While `a -> b`

has a `Functor`

instance, because the type is actually `(->) a b`

, and `b`

is in a *positive* position, its flipped version has a `Contravariant`

instance.

*Exercise 5*: Write the `Contravariant`

instance for `Op`

:

```
instance Contravariant (Op r) where
contramap :: (b -> a) -> Op r a -> Op r b
```

*Exercise 6*: Write a `Contravariant`

instance for `Comparison`

:

`newtype Comparison a = Comparison { getComparison :: a -> a -> Ordering }`

*Exercise 7*: Can you think of a type that has both `Functor`

and `Contravariant`

instances?

*Exercise 8*: Can you think of a type that can't have a `Functor`

nor a `Contravariant`

instance? These types are called `Invariant`

functors.