### Introducing Monads

The Functor, Applicative, and Monad typeclasses are pervasive across Haskell programs. These type classes help you address a wide variety of extremely common problems that arise when writing any number of real world programming problems.

You’ll learn about monads, applicatives, and functors and what laws govern them. You’ll also learn more about how to work with IO actions, and how to make use of other common data types, like the optional Maybe type.

You’ll be able to work effectively with any datatype that is a functor, applicative, or monad, and define your own instances for these type classes.

Throughout the remainder of this book we’ll make use of these typeclasses regularly.

## Flipping the Script

Try to write instances of `Functor`

, `Applicative`

, and `Monad`

for `List`

where
`Functor`

is defined in terms of `Applicative`

, and `Applicative`

is defined in
terms of `Monad`

. Is this possible? Why or why not?

### Hint 1

Some high level hint text

### Hint 2

Some more detailed hint text

### Hint 3

Even more detailed hint text

### Solution

A complete solution for the exercise

## Not a Functor

Imagine that we’ve created a new type to represent a *sorted* list of
values:

```
{-# LANGUAGE DerivingStrategies #-}
module SortedListFunctor (SortedList, insertSorted) where
data SortedList a = Empty | Cons a (SortedList a)
deriving stock (Eq, Show)
insertSorted :: Ord a => a -> SortedList a -> SortedList a
Empty = Cons a Empty
insertSorted a Cons b bs)
insertSorted a (| a >= b = Cons b (insertSorted a bs)
| otherwise = Cons a (Cons b bs)
```

Although `SortedList`

might be useful, it turns out that you can’t write a
*correct* instance of `Functor`

for a `SortedList`

. Try to define `Functor`

yourself and experiment with it’s behavior. See if you can figure out why you
can’t write a correct instance.

### Hint 1

Some high level hint text

### Hint 2

Some more detailed hint text

### Hint 3

Even more detailed hint text

### Solution

A complete solution for the exercise

## The Extended Functor Family

In addition to the standard `Functor`

class that you’ve used in this chapter,
there are other type classes that are related to `Functor`

but with somewhat
different behaviors.

#### Bifunctors

A `Bifunctor`

is like a `Functor`

but even moreso, because a `Bifunctor`

let’s
you map two different fields. The `Bifunctor`

class is defined in
`Data.Bifunctor`

. Let’s take a look at a definition for it:

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

Try to write an instance of `Bifunctor`

for `Either`

.

#### Contravariant Functors

The `Contravariant`

class from `Data.Functor.Contravariant`

in base defines a
`_contravariant_`

functor. Although we don’t normally refer to them this way,
the `Functor`

class that you’ve been working with so far is a

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

Try to create a new version of the `Function`

type that you defined earlier, and
then write an instance of `Contravariant`

for it. Can you also create an
instance of `Contravariant`

for your original definition of `Function`

? Why or
why not?

#### Profunctors

A `Profunctor`

is a combination of a `Bifunctor`

and a `Contravariant`

functor. `Profunctor`

isn’t defined in `base`

, but you’ll see it defined by some
other popular libraries. Like a `Bifunctor`

it works on types with two
arguments. Like `Contravariant`

functors, the first argument to a `Profunctor`

works “backwards”. Let’s take a look at a definition for `Profunctor`

:

```
class Profunctor f where
dimap :: (c -> a) -> (b -> d) -> f a b -> f c d
lmap :: (c -> a) -> f a b -> f c b
= dimap f id
lmap f
rmap :: (b -> d) -> f a b -> f a d
= dimap id f rmap f
```

Try to create an instance of `Profunctor`

for your original `Function`

type. Can
you write a valid instance? Why or why not? How does this differ from trying to
create a instance of `Contravariant`

for `Function`

?

### Hint 1

Some high level hint text

### Hint 2

Some more detailed hint text

### Hint 3

Even more detailed hint text

### Solution

A complete solution for the exercise