# Contravariant Functors Are Weird

Correct a demonstrate about nomenclature before we commence; I’ll exhaust “functor” to indicate the specific meaning of the conception:

A functor is a mapping between classes

and `Functor`

and `Contravariant`

to specify the typeclass encodings of functors.

Let’s commence up!

Contravariant functors are extraordinary aren’t they? Covariant functors (that are modelled by the `Functor`

typeclass) are rather straight forward but **contra**variant functors as their name implies appear to be your whole reverse.

Earlier than we get into what a contravariant functor is, it’s worthwhile to explore at the `Functor`

typeclass which we know and adore.

## Functor

A `Functor`

is defined as:

```
class Functor f where
fmap :: (a -> b) -> f a -> f b
```

We usually tag a `Functor`

to be a “container” or a “producer” of some form, where the feature provided to `fmap`

is utilized to the substances that are “contained” or “produced” in some form constructor^{1} `f`

.

A straight forward example would possibly presumably well be the record (`[]`

) form, that can signify zero or extra values. Given a `[a]`

we can turn it into a `[b]`

when given a feature `a -> b`

.

```
files [] a = [] | a : [a] -- an approximation of the [] files form
instance Functor [] where
fmap _ [] = []
fmap f (x: xs) = f x : fmap f xs
```

In the example under we convert a `[Int]`

into a `[String]`

given a feature `Int -> String`

:

```
import Knowledge.Semigroup ((<>))
myInts :: [Int]
myInts = [1 .. 5]
emptyInts :: [Int]
emptyInts = []
intToString :: Int -> String
intToString n = (show n) <> "!"
myStrings :: [String]
myStrings = fmap intToString myInts -- ["1!","2!","3!","4!","5!"]
myEmptyString :: []
myEmptyString = fmap intToString emptyInts -- []
```

But any other example would the `Seemingly`

files form, that represents a rate which will or would possibly presumably well now now not exist.

```
files Seemingly a = Nothing | Correct a
instance Functor Seemingly where
fmap _ Nothing = Nothing
fmap f (Correct x) = Correct (f x)
```

In the example under we convert a `Seemingly Int`

into a `Seemingly String`

given a feature `Int -> String`

:

```
import Knowledge.Semigroup ((<>))
maybeInt :: Seemingly Int
maybeInt = Correct 10
notInt :: Seemingly Int
notInt = Nothing
intToString :: Int -> String
intToString n = (show n) <> "!"
maybeString :: Seemingly String
maybeString = fmap intToString maybeInt -- Correct "10!"
notString :: Seemingly String
notString = fmap intToString notInt -- Nothing
```

The `Functor`

typeclass has regulations, that guarantee `Functor`

cases behave in a predictable way.

### Regulations

#### Identification

Essentially ought to you smash nothing to the associated rate of a `Functor`

, you get the same `Functor`

you started with.

#### Composition

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

If you happen to convert the tip result of a Functor by `fmap`

ing with a feature `g`

after which `fmap`

ing that result with a subsequent feature `f`

, it’s the same as composing functions `g`

and `f`

(`f . g`

) after which `fmap`

ing once.

Functor Regulations

### The Heinous Style of fmap

Now let’s explore at something a tiny bit a whole lot of. Let’s invent an files form to wrap a predicate of some form. A predicate is something that can attach in tips to a `Bool`

:

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

An example of a Predicate is **greaterThanTen**:

```
greaterThanTen :: Predicate Int
greaterThanTen = Predicate (n -> n > 10)
```

that checks whether or now now not a quantity is higher than ten.

We can flee with it **getPredicate** and an `Int`

:

```
getPredicate greateThanTen 5 -- False
getPredicate greateThanTen 11 -- Dazzling
```

It would be worthwhile to elaborate a `Functor`

instance for Predicate – snort if we now maintain got a `Predicate Int`

and we are seeking to turn out to be it into a `Predicate String`

once we now maintain got a `Int -> String`

feature. Let’s strive and enforce that:

```
instance Functor Predicate where
-- fmap (a -> b) -> Predicate a -> Predicate b
fmap f (Predicate p) = Predicate (b -> undefined)
fmap f (Predicate (a -> Bool)) = Predicate (b -> undefined) -- expanding p
fmap (a -> b) (Predicate (a -> Bool)) = Predicate (b -> undefined) -- expanding f
```

Now we’ve flee into a tiny notify:

How will we fabricate (a -> Bool) and (a -> b) to present us a (b -> Bool) ?

We’re given a `b`

but we don’t maintain access to any functions that after all exhaust a `b`

.

The problem is that we can’t. It’s on account of something known as “polarity” of the kind variable `a`

. No `Functor`

instance for you `Predicate`

.

## Polarity

Polarity is a technique of representing variance using the utter of form variables. Let’s retract a straightforward feature `a -> b`

as an illustration.

Characteristic Polarity

If a kind variable is in **input** utter adore `a`

it’s miles given a **detrimental** polarity. Whether it’s miles in an **output** utter adore `b`

then it’s miles given a **certain** polarity.

These polarities scheme straight to variant forms.

Particular | Covariant |

Harmful | Contravariant |

Each and every | Invariant |

What this means is that `Functor`

s (that are after all covariant functors) require a kind constructor in a covariant utter in expose for you to elaborate a `Functor`

instance for that form.

Let’s explore at a kind that we know has a `Functor`

instance adore `Seemingly`

:

Polarity of the Seemingly files form

We can seek that the kind variable `a`

happens in a covariant (or output) utter all thru the definition of the `Correct`

constructor.

Now let’s explore at the definition of `Predicate`

files form:

Polarity of the Predicate files form

We can seek that the kind variable `a`

happens in a contravariant (or input) utter. This ability that we can’t invent a (covariant) `Functor`

instance for this knowledge form.

But we are seeking to scheme issues! What will we smash?

## Contravariant

Welcome the `Contravariant`

typeclass to the stage! It’s defined as:

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

Snazzy! `Contravariant`

also takes some extra or less form constructor `f`

honest adore `Functor`

nonetheless it has this weirdly named `contramap`

feature rather than `fmap`

.

```
fmap :: (a -> b) -> f a -> f b -- Functor
contramap :: (a -> b) -> f b -> f a -- Contravariant
^^^
```

If we learn `fmap`

as:

If you happen to would possibly presumably well maintain an

`a`

in some context and a feature that takes that`a`

and converts it to a`b`

, I will give you a context with a`b`

in it.

we can then learn `contramap`

as:

If you happen to would possibly presumably well maintain a context that needs an

`a`

and a feature that can convert`b`

s to`a`

s, I will give you a context that needs`b`

s.

But that presumably doesn’t invent noteworthy sense. So let’s strive and explore at this when it involves our non-`Functor`

: `Predicate`

. `Predicate`

has a **need** for an `a`

, which it then uses to yelp if something about that `a`

is Dazzling or False.

Let’s strive and write a `Contravariant`

instance for `Predicate`

provided that we know that the kind `a`

in `Predicate`

happens in an input utter.

```
instance Contravariant Predicate where
-- contramp (a -> b) -> f b -> f a
contramap (a -> b) -> Predicate b -> Predicate a -- substituting for `f` for Predicate
contramap aToB (Predicate bToBool) = Predicate (a -> undefined)
```

Given that we now maintain got a feature `a -> b`

and basically a feature of form `b -> Bool`

(wrapped interior a `Predicate b`

), we can if given an `a`

, convert it to a `b`

using `aToB`

after which provide that `b`

to `bToBool`

to present us a `Bool`

.

Right here’s a barely long-fabricate implementation of the `Contravariant`

instance for `Predicate`

:

```
instance Contravariant Predicate where
contramap :: (a -> b) -> Predicate b -> Predicate a
contramap aToB (Predicate bToBool) =
Predicate $ a ->
let b = aToB a
bool = bToBool b
in bool
```

contramap on Predicate

or extra succinctly:

```
instance Contravariant Predicate where
contramap :: (a -> b) -> Predicate b -> Predicate a
contramap f (Predicate b) = Predicate $ b . f
```

We can seek from the definition of `Predicate a`

that each we are doing is working the provided feature `f`

**before** the feature interior `Predicate b`

. The reason we smash that’s to adapt a original input form to study an present input form to develop some functionality.

If we revisit the (covariant) `Functor`

instance for `Seemingly`

:

```
instance Functor Seemingly where
fmap _ Nothing = Nothing
fmap aToB (Correct a) = Correct (aToB a)
```

we can seek that the feature `aToB`

is flee **after** we now maintain got a rate of `a`

. We smash that to turn out to be a result of some form to 1 other form.

fmap on Seemingly

These are the a will must maintain differences between covariant and contravariant functors:

Functor | after | Convert outcomes |

Contravariant | before | Adapt inputs |

Now that we know the a will must maintain distinction between `Functor`

and `Contravariant`

, let’s explore at how we can exhaust `contramap`

with our `Predicate`

class.

Given that we already maintain a `Predicate`

that determines whether or now now not a quantity is higher than ten:

```
numGreaterThanTen :: Predicate Int
numGreaterThanTen = Predicate (n -> n > 10)
```

snort we are seeking to write one other `Predicate`

that verifies that the scale of String is higher than ten characters.

```
strLengthGreaterThanTen :: Predicate String
strLengthGreaterThanTen = Predicate (s -> (dimension s) > 10)
```

Sure, that’s rather contrived but undergo with me. Let’s also snort we now maintain got a `Particular person`

files form and we are seeking to clutch if a person’s name is over ten characters long – if that is so we attach in tips that to be a protracted name.

```
files Particular person = Particular person { personName :: String, personAge :: Int }
personLongName :: Predicate Particular person
personLongName = Predicate (p -> (dimension . personName $ p) > 10)
```

And we can flee these `Predicate`

s as:

```
getPredicate numGreaterThanTen 5 -- False
getPredicate numGreaterThanTen 20 -- Dazzling
getPredicate strLengthGreaterThanTen "hello" -- False
getPredicate strLengthGreaterThanTen "hello world" -- Dazzling
getPredicate personLongName $ Particular person "John" 30 -- False
getPredicate personLongName $ Particular person "Bartholomew" 30 -- Dazzling
```

And right here is stunning, but there’s some duplication all one of the best way thru each of the `Predicate`

s – particularly the part where we study a quantity to ten:

```
(n -> n > 10) -- Int
(s -> (dimension s) > 10) -- String
(p -> (dimension . personName $ p) > 10) -- Particular person
```

It’d be fine if we didn’t must repeat ourselves.

If we explore at the differences between `numGreaterThanTen`

, `strLengthGreaterThanTen`

and `personLongName`

we can seek that one of the best distinction is that one works on an `Int`

and the others work on `String`

and `Particular person`

respectively. `strLengthGreaterThanTen`

and `personLongName`

each convert their input forms to an `Int`

after which smash the same comparability:

```
Predicate ((n :: Int) ->
let num = id n
in num > 10 -- (1)
) -- numGreaterThanTen
Predicate ((s :: String) ->
let num = dimension s
in num > 10 -- (1)
) -- strLengthGreaterThanTen
Predicate ((p :: Particular person) ->
let name = personName p
num = dimension name
in num > 10 -- (1)
) -- personLongName
```

The above expansion of the functions demonstrates that even supposing the `Predicate`

s themselves maintain a whole lot of input forms, at the tip they are all converted to a quantity which is when put next against the volume ten. This is tagged with `(1)`

in the above example.

We would possibly presumably well additionally additionally seek that one of the best adjustments between the `Predicate`

s is the conversion from one form to 1 other **before** working our comparability feature `(1)`

. This is our clue that we can exhaust `contramap`

right here to reuse some functionality.

```
numGreaterThanTen :: Predicate Int
numGreaterThanTen = Predicate (n -> n > 10)
strLengthGreaterThanTen2 :: Predicate String
strLengthGreaterThanTen2 = contramap dimension numGreaterThanTen -- convert the String to an Int, then sprint it to numGreaterThanTen
personLongName2 :: Predicate Particular person
personLongName2 = contramap (dimension . personName) numGreaterThanTen -- convert the Particular person to an Int, then sprint it to numGreaterThanTen
```

We get the same outcomes as before:

```
getPredicate strLengthGreaterThanTen2 "hello" -- False
getPredicate strLengthGreaterThanTen2 "hello world" -- Dazzling
getPredicate personLongName2 $ Particular person "John" 30 -- False
getPredicate personLongName2 $ Particular person "Bartholomew" 30 -- Dazzling
```

Now we now maintain got rewritten `strLengthGreaterThanTen`

and `personLongName`

when it involves `numGreaterThanTen`

by honest working a feature before it to turn out to be the forms. This is a straight forward example of a Contravariant Functor where we can reuse some present functionality for a given form if we can convert from our other forms to that form thru some mapping feature.

We would possibly presumably well additionally additionally sprint a tiny bit additional and reuse even extra:

```
personLongName3 :: Predicate Particular person
personLongName3 = contramap personName strLengthGreaterThanTen -- convert the Particular person to a String, then sprint it to strLengthGreaterThanTen
```

### Regulations

Correct adore `Functor`

has regulations, `Contravariant`

also has regulations. This is awesome – on account of regulations invent our lives less difficult.

#### Identification

Essentially ought to you smash now now not alternate the associated rate of a `Contravariant`

functor, you get the same `Contravariant`

functor you started with.

#### Composition

`contramap f . contramap g = contramap (g . f)`

If you happen to convert the input to some `Contravariant`

functor by `contramap`

ing with feature `g`

after which convert its input to 1 other form by `contramap`

ing again with a feature `f`

, it’s the same as composing the functions `f`

and `g`

(`g . f`

) after which `contramap`

ing once. See the expose of composition is switched as against once we regarded at the `Functor`

regulations.

Contravariant Regulations

Let’s retract `Predicate`

as an illustration and strive out the identity legislation. The `Contravariant`

instance for `Predicate`

is defined as:

```
instance Contravariant Predicate where
contramap :: (a -> b) -> f b -> f a
contramap f (Predicate p) = Predicate (p . f)
```

Given that we now maintain got a `Predicate Int`

:

```
numGreaterThanTen :: Predicate Int
numGreaterThanTen = Predicate (n -> n > 10)
```

The exhaust of `contramap id`

on the above:

```
-- identity legislation
contramap id numGreaterThanTen == numGreaterThanTen
-- lhs
Predicate (p . f) -- applying contramap
Predicate (p . id) -- expanding f
Predicate (p) -- applying f
Predicate (n -> n > 10) -- expanding p
-- rhs
numGreaterThanTen
Predicate (n -> n > 10) -- expanding numGreaterThanTen
-- equality
lhs == rhs
Predicate (n -> n > 10) == Predicate (n -> n > 10)
```

As soon as extra using `Predicate`

as an illustration, let’s explore the compositional legislation of `Contravariant`

.

Given that we now maintain got the next `Predicate`

s:

```
numGreaterThanTen :: Predicate Int
numGreaterThanTen = Predicate (n -> n > 10)
dimension :: [a] -> Int
personName :: Particular person -> String
```

The exhaust of `numGreaterThanTen`

, with `dimension`

and `personName`

:

```
-- composition legislation
contramap personName . contramap dimension $ numGreaterThanTen = contramap (dimension . personName) numGreaterThanTen
-- lhs
contramap personName . contramap dimension $ numGreaterThanTen
contramap personName . contramap dimension $ Predicate (n -> n > 10) -- expanding numGreaterThanTen
contramap personName (Predicate $ str ->
let num = dimension str
bool = num > 10
in bool
) -- applying dimension
Predicate $ person ->
let str = personName person
num = dimension str
bool = num > 10
in bool
) -- applying personName
=> Predicate Particular person
-- rhs
contramap (dimension . personName) numGreaterThanTen
contramap (person ->
let str = personName person
num = dimension str
in num
) numGreaterThanTen -- expanding dimension . personName
Predicate (person ->
let str = personName person
num = dimension str
bool = num > 10 -- expanding numGreaterThanTen
in bool
)
=> Predicate Particular person
-- equality
lhs == rhs
Predicate (person ->
let str = personName person
num = dimension str
bool = num > 10
in bool
) ==
Predicate (person ->
let str = personName person
num = dimension str
bool = num > 10
in bool
)
```

### Combinators

There are some constructed-in combinators that sprint with `Contravariant`

.

#### Infix contramap

Linked to the `contramap`

feature the next functions will also be dilapidated infix:

```
-- infixl 4
(>$<) :: Contravariant f => (a -> b) -> f b -> f a
-- contramap :: Contravariant f => (a -> b) -> f b -> f a
```

A straight forward example of it in exhaust:

```
p5 :: Predicate Int
p5 = Predicate $ n -> n == 5
pLength5 :: Predicate [a]
pLength5 = dimension >$< p5
getPredicate pLength5 "hello"
-- True
getPredicate pLength5 "hello world"
-- False
```

Same as `contramap`

but with the parameters switched:

```
-- infixl 4
(>$$<) :: Contravariant f => f b -> (a -> b) -> f a
-- contramap :: Contravariant f => (a -> b) -> f b -> f a
```

#### Infix const

These combinators retract in a constant input and thoroughly ignore the input provided when working the `Contravariant`

instance.

```
-- infixl 4
(>$) :: b -> f b -> f a
```

It has a default implementation of:

```
(>$) :: b -> f b -> f a
(>$) = contramap . const
```

Let’s seek how that works:

```
-- const when given two values returns the first rate ignoring the 2d
const :: a -> b -> a
const x _ = x
contramap :: Contravariant f => (a -> b) -> f b -> f a
(>$) :: b -> f b -> f a
(>$) = contramap . const
(>$) b = contramap (const b) -- simplifying with b
(>$) b = contramap (a -> b) -- applying `const b`
(>$) b fb = contramap (a -> b) fb -- simplifying with fb
(>$) b fb = fa -- simplifying `contramap (a -> b) fb`
```

A straight forward example of it in exhaust:

```
p5 :: Predicate Int
p5 = Predicate $ n -> n == 5
pLength5 :: Predicate [a]
pLength5 = contramap dimension p5
getPredicate pLength5 "hello"
-- Dazzling
getPredicate pLength5 "hello world"
-- False
pAlwaysFalse :: Predicate [a]
pAlwaysFalse = 10 >$ p5
getPredicate pAlwaysFalse "hello"
-- False (on account of 10 /= 5)
getPredicate pAlwaysFalse "hello world"
-- False
```

Same as above but with the parameters switched:

```
-- infixl 4
($<) :: Contravariant f => f b -> b -> f a
```

### LogAction

Let’s explore at one other example of `Contravariant`

. Accept as true with you would possibly presumably well well maintain the next files form that encapsulates doing a tiny bit side develop on some polymorphic form `a`

:

`newtype LogAction a = LogAction { unlog :: a -> IO () }`

For our functions we can favor that we are going to exhaust this to log some rate either to the console or to a file or one other medium. This case has been tailored from the LogAction class of the CO-LOG logging library. No doubt take a look at out the library for genuine-world uses of `Contravariant`

and pals.

As we can seek the kind variable `a`

happens in input utter so we needs so as to elaborate a `Contravariant`

instance for it:

```
instance Contravariant LogAction where
contramap :: (b -> a) -> LogAction a -> LogAction b
contramap bToA logActionA = LogAction $ b -> unlog logActionA (bToA b)
```

There must be no surprises right here; we flee the provided feature `bToA`

on the input *before* passing it to the log action.

Right here’s a barely simplified implementation of the above:

```
instance Contravariant LogAction where
contramap f logActionA = LogAction $ unlog logActionA . f
```

So how will we exhaust `LogAction`

? Let’s elaborate a pair of implementations:

```
putStrLog :: LogAction String
putStrLog = LogAction putStr
putStrLnLog :: LogAction String
putStrLnLog = LogAction putStrLn
```

`putStrLog`

and `putStrLn`

are honest wrappers around `putStr`

and `putStrLn`

from `corrupt`

. Each and every log a String to the console, the variation being that `putStrLn`

sends a newline character to the console after each call.

Right here’s how we’d exhaust `putStrLnLog`

:

```
unlog putStrLnLog "Hello World"
-- Hello World
```

Be conscious that `LogAction`

*needs* an `a`

which on this case is a `String`

.

Now on account of we now maintain got the vitality of contravariance, we needs so as to log out other forms if we can convert them to a `String`

.

Listed below are some examples:

```
-- straight forward feature around contramap for LogAction
putStringlyLnLog :: (a -> String) -> LogAction a
putStringlyLnLog f = contramap f putStrLnLog
-- Now we can log Ints
putStrLnInt :: LogAction Int
putStrLnInt = putStringlyLnLog show
files Particular person = Particular person { name :: String, age :: Int }
-- personalized String illustration of Particular person
showPerson :: Particular person -> String
showPerson (Particular person name age) = "Particular person(name:" <> name <> ", age: " <> (show age) <> ")"
-- Now we can log of us
putStrLnPerson :: LogAction Particular person
putStrLnPerson = putStringlyLnLog showPerson
-- personalized String illustration of Particular individual that only displays age
showPersonAge :: Particular person -> String
showPersonAge person = "age: " <> (show $ age person)
-- Extra Particular person LogAction which outputs only age
putStrLnPersonAge :: LogAction Particular person
putStrLnPersonAge = putStringlyLnLog showPersonAge
```

Right here’s how we can flee the above:

```
unlog putStrLnInt 42
-- 42
unlog putStrLnPerson $ Particular person "Neelix" 60
-- Particular person(name:Neelix, age: 60)
unlog putStrLnPersonAge $ Particular person "Tuvok" 240
-- age: 240
```

We can seek that `LogAction`

for `Particular person`

, *needs* a `Particular person`

instance as input to develop the log action.

One thing which is presumably now now not glaring is that we would possibly presumably well additionally additionally adapt an input form to itself. It’s now now not essential to repeatedly convert from one form to 1 other.

Listed below are some example functions which we can exhaust with `contramap`

:

```
hello :: String -> String
hello = ("Hello" <>)
there :: String -> String
there = ("there" <>)
doctor :: String -> String
doctor = ("Doctor" <>)
area :: String -> String
area = (" " <>)
```

Right here’s how we fabricate the above functions into a `LogAction`

:

```
putStrLnGreeting :: LogAction String
putStrLnGreeting = contramap area . contramap doctor . contramap area . contramap there . contramap area . contramap hello $ putStrLnLog
```

Whoa! That’s even laborious to learn. What does it smash? Be conscious from the 2d legislation of `Contravariant`

that:

`contramap f . contramap g = contramap (g . f)`

Given that, we can rewrite our extremely compositional `LogAction`

adore so:

```
putStrLnGreeting :: LogAction String
putStrLnGreeting = contramap (hello . area . there . area . doctor . area) $ putStrLnLog
```

As a minimal right here is barely of extra readable – but the gargantuan thing is that gleaming the regulations helped us invent our code extra legible. But aloof – what does this smash?

The trick is to undergo in tips that `Contravaraint`

composition works in **reverse** to fashioned composition:

`contramap f . contramap g = contramap (g . f) -- detect the (g . f) rather than (f. g)`

This is how `putStrLnGreeting`

is evaluated:

```
putStrLnGreeting :: LogAction String
putStrLnGreeting = contramap (hello . area . there . area . doctor . area) $ putStrLnLog
unlog putStrLnGreeting "Switzer" -- flee the logger with "Switzer" because the input
-- the input is going to battle thru this sequence of functions:
-- (hello . area . there . area . doctor . area)
-- applying area
" " <> Switzer
-- applying doctor
"Doctor" <> " " <> Switzer
-- applying area
" " <> "Doctor" <> " " <> Switzer
-- applying there
"there" <> " " <> "Doctor" <> " " <> Switzer
-- applying area
" " <> "there" <> " " <> "Doctor" <> " " <> Switzer
-- applying hello
"Hello" <> " " <> "there" <> " " <> "Doctor" <> " " <> Switzer
-- final output:
-- Hello there Doctor Switzer
```

Let’s explore at one extra `LogAction`

which would possibly presumably well presumably be attention-grabbing; One where we ignore the input and return some constant output:

```
override :: a -> a -> a
override rate = const rate
```

A we talked about previously, `const`

is defined as `a -> b -> a`

, where it accepts two inputs but returns the associated rate of the first input (ignoring the 2d input).

Right here’s how we exhaust it with `LogAction`

:

```
qPutStrLn :: LogAction String
qPutStrLn = contramap (override "This is Q!!") putStrLnLog
-- flee it
unlog qPutStrLn "Picard J L"
-- This is Q!!
```

Now if our reminiscence serves, we needs so as to smash the same with `>$`

:

```
qPutStrLnOp :: LogAction String
qPutStrLnOp = "This is Q!!" >$ putStrLnLog
-- flee it
unlog qPutStrLnOp "Sisko B L"
-- This is Q!!
```

### Equality and Ordering

Now let’s explore at two barely of linked concepts: equality and ordering

#### Equivalence

Let’s imagine that we now maintain got a datatype known as `Equivalence`

that wraps an equality expression:

`newtype Equivalence a = Equivalence { getEquivalence :: a -> a -> Bool }`

Given two values of form `a`

the `getEquivalence`

feature will return a `Bool`

indicating in the occasion that they are equal or now now not.

Now we can seek that both `a`

form variables are in input utter. Let’s elaborate a `Contravariant`

instance for it:

```
instance Contravariant Equivalence where
contramap :: (a -> b) -> Equivalence b -> Equivalence a
contramap aToB (Equivalence eqB1B2) = Equivalence $ a1 a2 ->
let b1 = aToB a1
b2 = aToB a2
in eqB1B2 b1 b2
```

One thing essential to demonstrate is that the feature we offer to `contramap`

(`a -> b`

) is flee on twice – once on each of the input parameters (`b`

).

Polarity of Equivalence

Given an `Equivalence`

for `Int`

:

```
intEq :: Equivalence Int
intEq = Equivalence (==)
```

We can flee it as:

```
getEquivalence intEq 1 2
-- False
getEquivalence intEq 1 1
-- Dazzling
```

We can calculate the equivalence of other forms using `contramap`

:

```
strLengthEq :: Equivalence String
strLengthEq = contramap dimension intEq
files Particular person = Particular person { name :: String, age :: Int }
personAgeEq :: Equivalence Particular person -- equality by age
personAgeEq = contramap age intEq
personNameLengthEq :: Equivalence Particular person -- equality by dimension of name
personNameLengthEq = contramap name strLengthEq
```

Right here’s how we can flee the above:

```
-- t1 = Particular person "Tuvok1" 240
-- t2 = Particular person "Tuvok2" 340
-- t3 = Particular person "Neelix" 60
-- t4 = Particular person "Janeway" 40
getEquivalence personAgeEq t1 t2
-- False
getEquivalence personAgeEq t1 t1
-- Dazzling
getEquivalence personAgeEq t2 t2
-- Dazzling
getEquivalence personAgeEq t2 t3
-- False
getEquivalence personNameLengthEq t1 t2
-- Dazzling
getEquivalence personNameLengthEq t3 t4
-- False
getEquivalence personNameLengthEq t1 t4
-- False
```

#### Comparison

Let’s imagine that we now maintain got a datatype known as `Comparison`

that wraps a comparability expression:

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

Given two values of form `a`

the `getComparison`

feature will return an Ordering (`LT`

, `GT`

or `EQ`

) with recognize to each other.

Now we can seek that both `a`

form variables are in input utter as before. Let’s elaborate a `Contravariant`

instance for it:

```
instance Contravariant Comparison where
contramap :: (a -> b) -> Comparison b -> Comparison a
contramap aToB (Comparison cmpB1B2) = Comparison $ a1 a2 ->
let b1 = aToB a1
b2 = aToB a2
in cmpB1B2 b1 b2
```

Polarity of Comparison

We can seek that the wrappers for `Equivalence`

and `Comparison`

are practically the same, as are their `Contravariant`

cases.

Given a `Comparison`

for Int as:

```
intCmp :: Comparison Int
intCmp = Comparison study
```

We can flee it as:

```
getComparison intCmp 1 1
-- EQ
getComparison intCmp 1 2
-- LT
getComparison intCmp 2 1
-- GT
```

We can now calculate the comparability of other forms using `contramap`

:

```
strCmp :: Comparison String
strCmp = contramap dimension intCmp
personAgeCmp :: Comparison Particular person
personAgeCmp = contramap age intCmp
fstCmp :: Comparison a -> Comparison (a, b)
fstCmp compA = contramap fst compA
```

Nothing original right here. Let’s maintain a seek at learn the technique to form numbers. We exhaust the `sortBy`

feature defined in `Knowledge.List`

from the `corrupt`

package:

`sortBy :: (a -> a -> Ordering) -> [a] -> [a]`

We can seek from the sortBy feature definition that it would accept the guidelines wrapped in the `Comparison`

files form:

```
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
getComparison :: a -> a -> Ordering
```

Sorting numbers with the above feature:

```
-- unsortedNumbers = [3, 5, 1, 4, 2]
-- ascending form
sortBy (getComparison intCmp) unsortedNumbers
-- [1,2,3,4,5]
-- descending form
sortBy (flip $ getComparison intCmp) unsortedNumbers
-- [5,4,3,2,1]
```

See how we honest exhaust the flip feature to alternate between ascending and descending form:

`flip :: (a -> b -> c) -> b -> a -> c`

`flip`

honest adjustments the expose of input parameters. `flip`

is awesome 🙂 I saw this scheme first dilapidated at Roman Cheplyaka’s weblog.

But right here’s something attention-grabbing: since we know learn the technique to form `Int`

s we also know learn the technique to form of us by age thru `personAgeCmp`

! Let’s seek that in action:

```
-- unsortedPeople = [Person "Tuvok1" 240, Person "Janeway" 40, Person "Neelix" 60]
-- ascending form
sortBy (getComparison personAgeCmp) unsortedPeople
-- [Person {name = "Janeway", age = 40},Person {name = "Neelix", age = 60},Person {name = "Tuvok1", age = 240}]
-- descending form
sortBy (flip $ getComparison personAgeCmp)
-- [Person {name = "Tuvok1", age = 240},Person {name = "Neelix", age = 60},Person {name = "Janeway", age = 40}]
```

### Characteristic Kinds

A recurring feature will also be even supposing of being defined as:

`newtype RegularFunc a b = RegularFunc { getRegular :: a -> b }`

We can elaborate a `Functor`

instance for `RegularFunc`

on account of `b`

is in output utter. But what about `a`

, which is in input utter? More on that under.

Let’s retract what the definition of the `Functor`

form class looks adore:

```
class Functor f where
fmap :: (a -> b) -> f a -> f b
```

In the above declaration, `f`

is a kind constructor with one form gap. Given `RegularFunc`

which has two form holes (`a`

and `b`

), we now maintain got to absorb one in, in expose to exhaust it with the `Functor`

instance implementation. To complete this we repair `a`

and get the kind constructor `RegularFunc a`

. We can’t repair `b`

as partial utility of forms is performed from left to correct (holes can only be on the supreme).

```
instance Functor (RegularFunc a) where
fmap :: (b -> c) -> f b -> f c
fmap = (.)
```

We can’t elaborate a `Contravariant`

instance for `a`

on account of we now maintain got to repair `a`

(we can’t elaborate behaviour over it). All we now maintain got to play with is `b`

which is in output utter (and on account of this truth covariant)

Oh! Device on! If only we didn’t must repair `a`

. What if we would possibly presumably well repair `b`

instead? We don’t care about `b`

. `b`

is tiresome to us.

Let’s dream up this form of kind and get in touch with it `Op`

– for **op**posite of customary:

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

Now we can seek that the kind `b`

is in input utter all thru the guidelines form. It’s also on the supreme of `Op a b`

meaning we don’t must repair it.

`Op a b`

will also be a tiny bit confusing on account of we now maintain got switched the utter of form parameters `a`

and `b`

as they had been in `RegularFunc`

; `a`

is the output and `b`

is the input.

RegularFunc a b | Input | Output |

Op a b | Output | Input |

And guess what? We can now repair `a`

(which is now our output) and would possibly presumably well elaborate a `Contravariant`

instance for `Op`

:

```
instance Contravariant (Op a) where
contramap :: (c -> b) -> Op a b -> Op a c
contramap cToB (Op bToA) = Op $ c ->
let b = cToB c
in bToA b
```

Right here’s a straightforward example of learn the technique to exhaust it:

```
stringsLength :: Op Int [String]
stringsLength = Op $ sum . fmap dimension
unqiueStringsLength :: Op Int (S.Plot String)
unqiueStringsLength = contramap S.toList stringsLength
```

If we know learn the technique to sum all the lengths of a `[String]`

we can adapt that feature to sum the lengths of a `Plot`

of `String`

:

```
import Knowledge.Plot (fromList)
namesList = ["Paris", "Kim", "B'Elanna", "Seven"]
namesSet = fromList namesList
getOp stringsLength $ namesList
-- 21
getOp unqiueStringsLength $ namesSet
-- 21
```

Now `Predicate`

, `Comparison`

, `Equivalence`

and `Op`

seem adore worthwhile files structures. The comely files is that they exist already in the Knowledge.Functor.Contravariant package from `corrupt`

so that you simply don’t must write them yourself.

One attention-grabbing implementation a part of the `Comparison`

and `Equivalence`

`Contravariant`

cases is that they’re utilized using the `on`

feature:

```
newtype Equivalence a = Equivalence { getEquivalence :: a -> a -> Bool }
instance Contravariant Equivalence where
contramap f g = Equivalence $ on (getEquivalence g) f
```

The `on`

feature is defined as:

```
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
(.*.) `on` f = x y -> f x .*. f y
```

Essentially given a feature `b -> b -> c`

and a feature `a -> b`

, the 2d feature will be utilized to each input of form `a`

changing it to a `b`

after which the first feature is utilized on the reworked inputs. Such reuse. 🙂

## More Polarity

Let’s retract a seek at the `CallbackRunner`

example from FP Entire:

```
newtype CallbackRunner a =
CallbackRunner {
runCallback :: (a -> IO ()) -> IO ()
}
```

Form variable `a`

is in input utter so we needs so as to write a `Contravariant`

instance for it:

```
instance Contravariant CallbackRunner where
contramap :: (a -> b) -> CallbackRunner b -> CallbackRunner a
contramap aToB (CallbackRunner runCallbackB) = CallbackRunner $ aToIO ->
runCallbackB $ b ->
let a = undefined -- where will we get an `a` from?
in aToIO a
-- if we had a (b -> a) we would possibly presumably well convert the `b` to an `a`
```

Hmm. Now it looks adore we now maintain got a notify. There doesn’t appear to anyway for us to get an `a`

to sprint to `aToIO`

to complete the implementation. We maintain a `b`

and if there became once a feature `b -> a`

rather than our `a -> b`

, we would possibly presumably well convert that `b`

to an `a`

and it would possibly well actually presumably well well all work.

This is on account of there’s extra to the polarity yarn than I’ve shared up till now. Whereas `a`

is in input utter in `a -> IO()`

, it’s polarity adjustments when it’s also dilapidated as an input to the feature `(a -> IO ()) -> IO ()`

. I previously talked about that an input utter is a `detrimental`

polarity and an output utter is a `certain`

polarity.

To determine the closing polarity of something we now maintain got to multiply its polarities at each context it’s miles dilapidated interior in the feature definition. More on this under.

Polarity multiplication is similar to the multiplication of certain and detrimental numbers:

### Polarity Multiplication Table

Particular | x | Particular | Particular |

Particular | x | Harmful | Harmful |

Harmful | x | Particular | Harmful |

Harmful | x | Harmful | Particular |

Let’s strive and figure out the polarity of `a`

given our original found multiplication skills. Given `runCallback`

:

`runCallback :: (a -> IO ()) -> IO ()`

`a`

is in input or detrimental utter in:

but interior complete feature it’s a barely a whole lot of yarn:

```
(a -> IO ()) -> IO () -- func
x = (a -> IO ()) -- assigning (a -> IO ()) to x in func
x -> IO () -- substituting x in func
```

We can seek that `x`

in the above example is in input or detrimental utter as properly. Given that `x`

is `a -> IO ()`

:

```
(a -> IO ()) -> IO ()
-- a -> IO (a is detrimental)
-- (a -> IO ()) -> IO () (your whole parenthesis are in detrimental utter)
-- polarity of a: detrimental detrimental = certain
```

Polarity Multiplication

Given that `a`

is now in output or certain utter, we needs so as to write a `Functor`

instance for it:

```
instance Functor CallbackRunner where
fmap :: (a -> b) -> CallbackRunner a -> CallbackRunner b
fmap aToB (CallbackRunner runCallbackA) = CallbackRunner $ bToIO ->
runCallbackA $ a ->
let b = aToB a
result = bToIO b
in result
```

And we can!! If you happen to’d possess to dig extra into polarities there are some comely exercises at the FP Entire article.

## Invariant Functors

We briefly talked about invariant functors when speaking about Polarity but by no technique talked about them again till now. The `Invariant`

typeclass is the guardian typeclass of both `Functor`

and `Contravariant`

)

Simplified Functor Hierarchy

Given that this put up is rather long, I’m only going to claim that `Invariant`

has both covariant and contravariant functions in its definition:

```
class Invariant f where
invmap :: (a -> b) -> (b -> a) -> f a -> f b
```

where `a -> b`

is the feature to exhaust if `f a`

is a `Functor`

and `b -> a`

is the feature to exhaust if `f a`

is `Contravariant`

.

I would possibly presumably well write one other article about invariant functors if I if truth be told feel the need for it, but for the time being checkout these articles to get you started.

## Abstract

Optimistically this has shed some gentle onto contravariant functors and one of the best way they are dilapidated and one of the best way they’ll also be utilized. In a future article I’m hoping to quilt `Divisible`

and `Decidable`

typeclasses that blueprint up from `Contravariant`

.

The offer for this article will also be found on Github.

A tall “Thank You” to George Wilson for interesting me to dig deeper into this subject alongside with his gleaming presentations on Functors.

A tall thanks also to Andrew Newman who reviewed this article.

## Hyperlinks

### Articles

- Functor Optics – Oleg’s Gists
- 24 days of Hackage – Contravariant – Ocharles
- Covariance and Contravariance – FP Entire
- Working out Contravariance – Form classes
- CO-LOG – Kowainik

### Video

- The Extended Functor Family – George Wilson
- Contravariant Functors – The Diversified Facet of the Coin – George Wilson
- Fun with Profunctors – Phil Freeman
- A Fistful of Functors – Itamar Ravid

### Books

### Questions and Solutions

- Taking a look for an abstraction to fabricate – Reddit
- datafunctorcontravariant some straight forward applications – Reddit
- The inducement in the serve of Contravariant – Reddit

### Programs

## Definitions

### Form constructor (1)

An files form that needs one or extra form variables to be thoroughly defined.

Shall we embrace, `Seemingly`

is a kind constructor and `Seemingly Int`

is a kind.