# # Bifunctor

## # Common instances of Bifunctor

### # Two-element tuples

`(,)`

is an example of a type that has a `Bifunctor`

instance.

```
instance Bifunctor (,) where
bimap f g (x, y) = (f x, g y)
```

`bimap`

takes a pair of functions and applies them to the tuple's respective components.

```
bimap (+ 2) (++ "nie") (3, "john") --> (5,"johnnie")
bimap ceiling length (3.5 :: Double, "john" :: String) --> (4,4)
```

### # `Either`

`Either`

's instance of `Bifunctor`

selects one of the two functions to apply depending on whether the value is `Left`

or `Right`

.

```
instance Bifunctor Either where
bimap f g (Left x) = Left (f x)
bimap f g (Right y) = Right (g y)
```

## # Definition of Bifunctor

`Bifunctor`

is the class of types with two type parameters (`f :: * -> * -> *`

), both of which can be covariantly mapped over simultaneously.

```
class Bifunctor f where
bimap :: (a -> c) -> (b -> d) -> f a b -> f c d
```

`bimap`

can be thought of as applying a pair of `fmap`

operations to a datatype.

A correct instance of `Bifunctor`

for a type `f`

must satisfy the **bifunctor laws**, which are analogous to the **functor laws** (opens new window):

```
bimap id id = id -- identity
bimap (f . g) (h . i) = bimap f h . bimap g i -- composition
```

The `Bifunctor`

class is found in the `Data.Bifunctor`

module. For GHC versions >7.10, this module is bundled with the compiler; for earlier versions you need to install the `bifunctors`

package.

## # first and second

If mapping covariantly over only the first argument, or only the second argument, is desired, then `first`

or `second`

ought to be used (in lieu of `bimap`

).

```
first :: Bifunctor f => (a -> c) -> f a b -> f c b
first f = bimap f id
second :: Bifunctor f => (b -> d) -> f a b -> f a d
second g = bimap id g
```

For example,

```
ghci> second (+ 2) (Right 40)
Right 42
ghci> second (+ 2) (Left "uh oh")
Left "uh oh"
```

#### # Syntax

- bimap :: (a -> b) -> (c -> d) -> p a c -> p b d
- first :: (a -> b) -> p a c -> p b c
- second :: (b -> c) -> p a b -> p a c

#### # Remarks

A run of the mill `Functor`

is covariant in a **single** type parameter. For instance, if `f`

is a `Functor`

, then given an `f a`

, and a function of the form `a -> b`

, one can obtain an `f b`

(through the use of `fmap`

).

A `Bifunctor`

is covariant in **two** type parameters. If `f`

is a `Bifunctor`

, then given an `f a b`

, and two functions, one from `a -> c`

, and another from `b -> d`

, then one can obtain an `f c d`

(using `bimap`

).

`first`

should be thought of as an `fmap`

over the first type parameter, `second`

as an `fmap`

over the second, and `bimap`

should be conceived as mapping two functions covariantly over the first and second type parameters, respectively.