-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #859 from vpavkin/contravariant-docs
Add Contravariant documentation page
- Loading branch information
Showing
2 changed files
with
81 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
--- | ||
layout: default | ||
title: "Contravariant" | ||
section: "typeclasses" | ||
source: "https://github.com/non/cats/blob/master/core/src/main/scala/cats/functor/Contravariant.scala" | ||
scaladoc: "#cats.functor.Contravariant" | ||
--- | ||
# Contravariant | ||
|
||
The `Contravariant` type class is for functors that define a `contramap` | ||
function with the following type: | ||
|
||
```scala | ||
def contramap[A, B](f: B => A): F[A] => F[B] | ||
``` | ||
|
||
It looks like regular (also called `Covariant`) [`Functor`](functor.html)'s `map`, | ||
but with the `f` transformation reversed. | ||
|
||
Generally speaking, if you have some context `F[A]` for type `A`, | ||
and you can get an `A` value out of a `B` value — `Contravariant` allows you to get the `F[B]` context for `B`. | ||
|
||
Examples of `Contravariant` instances are [`Show`](show.html) and `scala.math.Ordering` (along with `algebra.Order`). | ||
|
||
## Contravariant instance for Show. | ||
|
||
Say we have class `Money` with a `Show` instance, and `Salary` class. | ||
|
||
```tut:silent | ||
import cats._ | ||
import cats.implicits._ | ||
case class Money(amount: Int) | ||
case class Salary(size: Money) | ||
implicit val showMoney: Show[Money] = Show.show(m => s"$$${m.amount}") | ||
``` | ||
|
||
If we want to show a `Salary` instance, we can just convert it to a `Money` instance and show it instead. | ||
|
||
Let's use `Show`'s `Contravariant`: | ||
|
||
```tut | ||
implicit val showSalary: Show[Salary] = showMoney.contramap(_.size) | ||
Salary(Money(1000)).show | ||
``` | ||
|
||
## Contravariant instance for scala.math.Ordering. | ||
|
||
`Show` example is trivial and quite far-fetched, let's see how `Contravariant` can help with orderings. | ||
|
||
`scala.math.Ordering` typeclass defines comparison operations, e.g. `compare`: | ||
|
||
```tut | ||
Ordering.Int.compare(2, 1) | ||
Ordering.Int.compare(1, 2) | ||
``` | ||
|
||
There's also a method, called `by`, that creates new `Orderings` out of existing ones: | ||
|
||
```scala | ||
def by[T, S](f: T => S)(implicit ord: Ordering[S]): Ordering[T] | ||
``` | ||
|
||
In fact, it is just `contramap`, defined in a slightly different way! We supply `T => S` to receive `F[S] => F[T]` back. | ||
|
||
So let's use it in our advantage and get `Ordering[Money]` for free: | ||
|
||
```tut | ||
// we need this for `<` to work | ||
import scala.math.Ordered._ | ||
implicit val moneyOrdering: Ordering[Money] = Ordering.by(_.amount) | ||
Money(100) < Money(200) | ||
``` | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters