**Table of Contents**

Web clients and servers often pass information around as a simple textual list of key-value pairs.

name=Attila+%42The+Hun%42&occupation=Khan

The encoding is named
`application/x-www-form-urlencoded`

, and it's easy to
understand. Each key-value pair is separated by an
“`&`

” character. Within a pair, a
key is a series of characters, followed by an
“`=`

”, followed by a value.

We can obviously represent a key as a String,
but the HTTP specification is not clear about whether a key must
be followed by a value. We can capture this ambiguity by
representing a value as a Maybe String. If we use
`Nothing`

for a value, then there was no value
present. If we wrap a string in `Just`

, then there
was a value. Using Maybe lets us distinguish
between “no value” and “empty
value”.

Haskell programmers use the name *association
list* for the type [(a, b)], where we
can think of each element as an association between a key and a
value. The name originates in the Lisp community, where it's
usually abbreviated as an *alist*. We could
thus represent the above string as the following Haskell
value.

-- file: ch15/MovieReview.hs [("name", Just "Attila \"The Hun\""), ("occupation", Just "Khan")]

In the section called “Parsing an URL-encoded query string”, we'll parse an
`application/x-www-form-urlencoded`

string, and
represent the result as an alist of [(String, Maybe
String)]. Let's say we want to use one of these alists
to fill out a data structure.

-- file: ch15/MovieReview.hs data MovieReview = MovieReview { revTitle :: String , revUser :: String , revReview :: String }

We'll begin by belabouring the obvious with a naive function.

-- file: ch15/MovieReview.hs simpleReview :: [(String, Maybe String)] -> Maybe MovieReview simpleReview alist = case lookup "title" alist of Just (Just title@(_:_)) -> case lookup "user" alist of Just (Just user@(_:_)) -> case lookup "review" alist of Just (Just review@(_:_)) -> Just (MovieReview title user review) _ -> Nothing -- no review _ -> Nothing -- no user _ -> Nothing -- no title

It only returns a MovieReview if the alist contains all of the necessary values, and they're all non-empty strings. However, the fact that it validates its inputs is its only merit: it suffers badly from the “staircasing” that we've learned to be wary of, and it knows the intimate details of the representation of an alist.

Since we're now well acquainted with the Maybe monad, we can tidy up the staircasing.

-- file: ch15/MovieReview.hs maybeReview alist = do title <- lookup1 "title" alist user <- lookup1 "user" alist review <- lookup1 "review" alist return (MovieReview title user review) lookup1 key alist = case lookup key alist of Just (Just s@(_:_)) -> Just s _ -> Nothing

Although this is much tidier, we're still repeating
ourselves. We can take advantage of the fact that the
`MovieReview`

constructor acts as a normal, pure
function by *lifting* it into the monad, as
we discussed in the section called “Mixing pure and monadic code”.

-- file: ch15/MovieReview.hs liftedReview alist = liftM3 MovieReview (lookup1 "title" alist) (lookup1 "user" alist) (lookup1 "review" alist)

We still have some repetition here, but it is dramatically reduced, and also more difficult to remove.

Although using `liftM3`

tidies up our
code, we can't use a `liftM`

-family function
to solve this sort of problem in general, because they're only
defined up to `liftM5`

by the standard
libraries. We could write variants up to whatever number we
pleased, but that would amount to drudgery.

If we had a constructor or pure function that took, say, ten parameters, and decided to stick with the standard libraries you might think we'd be out of luck.

Of course, our toolbox isn't yet empty. In
`Control.Monad`

, there's a function named
`ap`

with an interesting type
signature.

`ghci>`

`:m +Control.Monad`

`ghci>`

ap :: (Monad m) => m (a -> b) -> m a -> m b`:type ap`

You might wonder who would put a single-argument pure
function inside a monad, and why. Recall, however, that
*all* Haskell functions really take only one
argument, and you'll begin to see how this might relate to the
`MovieReview`

constructor.

`ghci>`

MovieReview :: String -> String -> String -> MovieReview`:type MovieReview`

We can just as easily write that type as String ->
(String -> (String -> MovieReview)). If we use
plain old `liftM`

to lift
`MovieReview`

into the `Maybe`

monad,
we'll have a value of type Maybe (String -> (String
-> (String -> MovieReview))). We can now see
that this type is suitable as an argument for
`ap`

, in which case the result type will be
Maybe (String -> (String -> MovieReview)). We
can pass this, in turn, to `ap`

, and continue
to chain until we end up with this definition.

-- file: ch15/MovieReview.hs apReview alist = MovieReview `liftM` lookup1 "title" alist `ap` lookup1 "user" alist `ap` lookup1 "review" alist

We can chain applications of
`ap`

like this as many times as we need to,
thereby bypassing the `liftM`

family of
functions.

Another helpful way to look at
`ap`

is that it's the monadic equivalent of
the familiar `($)`

operator: think of
pronouncing `ap`

as
*apply*. We can see this clearly when we
compare the type signatures of the two functions.

`ghci>`

($) :: (a -> b) -> a -> b`:type ($)`

`ghci>`

ap :: (Monad m) => m (a -> b) -> m a -> m b`:type ap`

In fact, `ap`

is usually defined as
either `liftM2 id`

or `liftM2 ($)`

.

Here's a simple representation of a person's phone numbers.

-- file: ch15/VCard.hs data Context = Home | Mobile | Business deriving (Eq, Show) type Phone = String albulena = [(Home, "+355-652-55512")] nils = [(Mobile, "+47-922-55-512"), (Business, "+47-922-12-121"), (Home, "+47-925-55-121"), (Business, "+47-922-25-551")] twalumba = [(Business, "+260-02-55-5121")]

Suppose we want to get in touch with someone to make a personal call. We don't want their business number, and we'd prefer to use their home number (if they have one) instead of their mobile number.

-- file: ch15/VCard.hs onePersonalPhone :: [(Context, Phone)] -> Maybe Phone onePersonalPhone ps = case lookup Home ps of Nothing -> lookup Mobile ps Just n -> Just n

Of course, if we use Maybe as the result type, we can't accommodate the possibility that someone might have more than one number that meet our criteria. For that, we switch to a list.

-- file: ch15/VCard.hs allBusinessPhones :: [(Context, Phone)] -> [Phone] allBusinessPhones ps = map snd numbers where numbers = case filter (contextIs Business) ps of [] -> filter (contextIs Mobile) ps ns -> ns contextIs a (b, _) = a == b

Notice that these two functions structure their `case`

expressions similarly: one alternative handles the case where
the first lookup returns an empty result, while the other
handles the non-empty case.

`ghci>`

Nothing`onePersonalPhone twalumba`

`ghci>`

Just "+355-652-55512"`onePersonalPhone albulena`

`ghci>`

["+47-922-12-121","+47-922-25-551"]`allBusinessPhones nils`

Haskell's `Control.Monad`

module defines a
typeclass, MonadPlus, that lets us abstract the
common pattern out of our `case`

expressions.

-- file: ch15/VCard.hs class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a

The value `mzero`

represents an empty result,
while `mplus`

combines two results into one.
Here are the standard definitions of `mzero`

and
`mplus`

for Maybe and
lists.

-- file: ch15/VCard.hs instance MonadPlus [] where mzero = [] mplus = (++) instance MonadPlus Maybe where mzero = Nothing Nothing `mplus` ys = ys xs `mplus` _ = xs

We can now use `mplus`

to get
rid of our `case`

expressions entirely. For variety, let's
fetch one business and all personal phone numbers.

-- file: ch15/VCard.hs oneBusinessPhone :: [(Context, Phone)] -> Maybe Phone oneBusinessPhone ps = lookup Business ps `mplus` lookup Mobile ps allPersonalPhones :: [(Context, Phone)] -> [Phone] allPersonalPhones ps = map snd $ filter (contextIs Home) ps `mplus` filter (contextIs Mobile) ps

In these functions, because we know that
`lookup`

returns a value of type
Maybe, and `filter`

returns a
list, it's obvious which version of `mplus`

is going to be used in each case.

What's more interesting is that we can use
`mzero`

and `mplus`

to write
functions that will be useful for *any*
MonadPlus instance. As an example, here's the
standard `lookup`

function, which returns a
value of type Maybe.

-- file: ch15/VCard.hs lookup :: (Eq a) => a -> [(a, b)] -> Maybe b lookup _ [] = Nothing lookup k ((x,y):xys) | x == k = Just y | otherwise = lookup k xys

We can easily generalise the result type to any instance of MonadPlus as follows.

-- file: ch15/VCard.hs lookupM :: (MonadPlus m, Eq a) => a -> [(a, b)] -> m b lookupM _ [] = mzero lookupM k ((x,y):xys) | x == k = return y `mplus` lookupM k xys | otherwise = lookupM k xys

This lets us get either no result or one, if our result type is Maybe; all results, if our result type is a list; or something more appropriate for some other exotic instance of MonadPlus.

For small functions, such as those we present above, there's
little benefit to using `mplus`

. The
advantage lies in more complex code and in code that is
independent of the monad in which it executes. Even if you
don't find yourself needing MonadPlus for your own
code, you are likely to encounter it in other people's
projects.

Even though the `mplus`

function
contains the text “plus”, you should not think of
it as necessarily implying that we're trying to add two
values.

Depending on the monad we're working in,
`mplus`

*may* implement an
operation that looks like addition. For example,
`mplus`

in the list monad is implemented as
the `(++)`

operator.

`ghci>`

[1,2,3,4,5,6]`[1,2,3] `mplus` [4,5,6]`

However, if we switch to another monad, the obvious similarity to addition falls away.

`ghci>`

Just 1`Just 1 `mplus` Just 2`

Instances of the MonadPlus typeclass must follow a few simple rules, in addition to the usual monad rules.

An instance must *short circuit* if
`mzero`

appears on the left of a bind expression.
In other words, an expression `mzero >>= f`

must evaluate to the same result as `mzero`

alone.

-- file: ch15/MonadPlus.hs mzero >>= f == mzero

An instance must short circuit if `mzero`

appears on the *right* of a sequence
expression.

-- file: ch15/MonadPlus.hs v >> mzero == mzero

When we introduced the `fail`

function in the section called “The Monad typeclass”, we took pains to warn against its
use: in many monads, it's implemented as a call to `error`

,
which has unpleasant consequences.

The MonadPlus typeclass gives us a gentler
way to fail a computation, without `fail`

or `error`

blowing
up in our faces. The rules that we introduced above allow us
to introduce an `mzero`

into our code wherever we
need to, and computation will short circuit at that
point.

In the `Control.Monad`

module, the standard
function `guard`

packages up this idea in a
convenient form.

-- file: ch15/MonadPlus.hs guard :: (MonadPlus m) => Bool -> m () guard True = return () guard False = mzero

As a simple example, here's a function that takes a number
`x`

and computes its value modulo some other
number `n`

. If the result is zero, it
returns `x`

, otherwise the current monad's
`mzero`

.

-- file: ch15/MonadPlus.hs x `zeroMod` n = guard ((x `mod` n) == 0) >> return x

In the section called “Using the state monad: generating random values”, we showed how to use the State monad to give ourselves access to random numbers in a way that is easy to use.

A drawback of the code we developed is that it's
*leaky*: someone who uses it knows that
they're executing inside the State monad. This
means that they can inspect and modify the state of the random
number generator just as easily as we, the authors, can.

Human nature dictates that if we leave our internal workings exposed, someone will surely come along and monkey with them. For a sufficiently small program, this may be fine, but in a larger software project, when one consumer of a library modifies its internals in a way that other consumers are not prepared for, the resulting bugs can be among the hardest of all to track down. These bugs occur at a level where we're unlikely to question our basic assumptions about a library until long after we've exhausted all other avenues of inquiry.

Even worse, once we leave our implementation exposed for a while, and some well-intentioned person inevitably bypasses our APIs and uses the implementation directly, we create a nasty quandary for ourselves if we need to fix a bug or make an enhancement. Either we can modify our internals, and break code that depends on them; or we're stuck with our existing internals, and must try to find some other way to make the change we need.

How can we revise our random number monad so that the fact
that we're using the State monad is hidden? We
need to somehow prevent our users from being able to call
`get`

or `put`

. This is not difficult to
do, and it introduces some tricks that we'll reuse often in
day-to-day Haskell programming.

To widen our scope, we'll move beyond random numbers, and
implement a monad that supplies unique values of
*any* kind. The name we'll give to our monad
is Supply. We'll provide the execution function,
`runSupply`

, with a list of values; it will
be up to us to ensure that each one is unique.

-- file: ch15/Supply.hs runSupply :: Supply s a -> [s] -> (a, [s])

The monad won't care what the values are: they might be random numbers, or names for temporary files, or identifiers for HTTP cookies.

Within the monad, every time a consumer asks for a value,
the `next`

action will take the next one from
the list and give it to the consumer. Each value is wrapped in
a Maybe constructor in case the list isn't long
enough to satisfy the demand.

-- file: ch15/Supply.hs next :: Supply s (Maybe s)

To hide our plumbing, in our module declaration we only
export the type constructor, the execution function, and the
`next`

action.

-- file: ch15/Supply.hs module Supply ( Supply , next , runSupply ) where

Since a module that imports the library can't see the internals of the monad, it can't manipulate them.

Our plumbing is exceedingly simple: we use a `newtype`

declaration to wrap the existing State
monad.

-- file: ch15/Supply.hs import Control.Monad.State newtype Supply s a = S (State [s] a)

The `s`

parameter is the type
of the unique values we are going to supply, and `a`

is the usual type parameter that
we must provide in order to make our type a monad.

Our use of `newtype`

for the Supply
type and our module header join forces to prevent our clients
from using the State monad's
`get`

and `set`

actions.
Because our module does not export the `S`

data
constructor, clients have no programmatic way to see that we're
wrapping the State monad, or to access it.

At this point, we've got a type, Supply, that
we need to make an instance of the Monad type
class. We could follow the usual pattern of defining `(>>=)`

and
`return`

, but this would be pure boilerplate code. All we'd be
doing is wrapping and unwrapping the State monad's
versions of `(>>=)`

and `return`

using our `S`

value
constructor. Here is how such code would look.

-- file: ch15/AltSupply.hs unwrapS :: Supply s a -> State [s] a unwrapS (S s) = s instance Monad (Supply s) where s >>= m = S (unwrapS s >>= unwrapS . m) return = S . return

Haskell programmers are not fond of boilerplate, and sure enough, GHC has a lovely language extension that eliminates the work. To use it, we add the following directive to the top of our source file, before the module header.

-- file: ch15/Supply.hs {-# LANGUAGE GeneralizedNewtypeDeriving #-}

Usually, we can only automatically derive instances of a
handful of standard typeclasses, such as Show and
Eq. As its name suggests, the
`GeneralizedNewtypeDeriving`

extension broadens our
ability to derive typeclass instances, and it is specific to
`newtype`

declarations. If the type we're wrapping is an
instance of any typeclass, the extensions can
automatically make our new type an instance of that typeclass
as follows.

-- file: ch15/Supply.hs deriving (Monad)

This takes the underlying type's implementations of `(>>=)`

and `return`

, adds the necessary wrapping and unwrapping with
our `S`

data constructor, and uses the new versions
of those functions to derive a Monad instance for
us.

What we gain here is very useful beyond just this example.
We can use `newtype`

to wrap any underlying type; we selectively
expose only those typeclass instances that we want; and we
expend almost no effort to create these narrower, more
specialised types.

Now that we've seen the
`GeneralizedNewtypeDeriving`

technique, all that
remains is to provide definitions of `next`

and `runSupply`

.

-- file: ch15/Supply.hs next = S $ do st <- get case st of [] -> return Nothing (x:xs) -> do put xs return (Just x) runSupply (S m) xs = runState m xs

If we load our module into **ghci**, we can try it out in a few
simple ways.

`ghci>`

[1 of 1] Compiling Supply ( Supply.hs, interpreted ) Ok, modules loaded: Supply.`:load Supply`

`ghci>`

Loading package mtl-1.1.0.0 ... linking ... done. (Just 1,[2,3])`runSupply next [1,2,3]`

`ghci>`

((Just 1,Just 2),[3])`runSupply (liftM2 (,) next next) [1,2,3]`

`ghci>`

((Just 1,Nothing),[])`runSupply (liftM2 (,) next next) [1]`

We can also verify that the State monad has not somehow leaked out.

`ghci>`

data Supply s a next :: Supply s (Maybe s) runSupply :: Supply s a -> [s] -> (a, [s])`:browse Supply`

`ghci>`

data Supply s a -- Defined at Supply.hs:17:8-13 instance Monad (Supply s) -- Defined at Supply.hs:17:8-13`:info Supply`

If we want to use our Supply monad as a source of random numbers, we have a small difficulty to face. Ideally, we'd like to be able to provide it with an infinite stream of random numbers. We can get a StdGen in the IO monad, but we must “put back” a different StdGen when we're done. If we don't, the next piece of code to get a StdGen will get the same state as we did. This means it will generate the same random numbers as we did, which is potentially catastrophic.

From the parts of the `System.Random`

module we've seen so far, it's difficult to reconcile these
demands. We can use `getStdRandom`

, whose
type ensures that when we get a StdGen, we put
one back.

`ghci>`

getStdRandom :: (StdGen -> (a, StdGen)) -> IO a`:type getStdRandom`

We can use `random`

to get back a new
StdGen when they give us a random number. And we
can use `randoms`

to get an infinite list
of random numbers. But how do we get both an infinite list of
random numbers *and* a new
StdGen?

The answer lies with the RandomGen type
class's `split`

function, which takes one
random number generator, and turns it into two generators.
Splitting a random generator like this is a most unusual thing
to be able to do: it's obviously tremendously useful in a pure
functional setting, but essentially never either necessary or
provided by an impure language.

Using the `split`

function, we can use
one StdGen to generate an infinite list of random
numbers to feed to `runSupply`

, while we
give the other back to the IO monad.

-- file: ch15/RandomSupply.hs import Supply import System.Random hiding (next) randomsIO :: Random a => IO [a] randomsIO = getStdRandom $ \g -> let (a, b) = split g in (randoms a, b)

If we've written this function properly, our example ought to print a different random number on each invocation.

`ghci>`

[1 of 2] Compiling Supply ( Supply.hs, interpreted ) [2 of 2] Compiling RandomSupply ( RandomSupply.hs, interpreted ) Ok, modules loaded: RandomSupply, Supply.`:load RandomSupply`

`ghci>`

<interactive>:1:17: Ambiguous occurrence `next' It could refer to either `Supply.next', imported from Supply at RandomSupply.hs:4:0-12 (defined at Supply.hs:32:0) or `System.Random.next', imported from System.Random`(fst . runSupply next) `fmap` randomsIO`

`ghci>`

<interactive>:1:17: Ambiguous occurrence `next' It could refer to either `Supply.next', imported from Supply at RandomSupply.hs:4:0-12 (defined at Supply.hs:32:0) or `System.Random.next', imported from System.Random`(fst . runSupply next) `fmap` randomsIO`

Recall that our `runSupply`

function
returns both the result of executing the monadic action and
the unconsumed remainder of the list. Since we passed it an
infinite list of random numbers, we compose with
`fst`

to ensure that we don't get drowned
in random numbers when **ghci** tries to print the
result.

The pattern of applying a function to one element of a pair, and constructing a new pair with the other original element untouched, is common enough in Haskell code that it has been turned into standard code.

In the `Control.Arrow`

module are two
functions, `first`

and
`second`

, that perform this
operation.

`ghci>`

`:m +Control.Arrow`

`ghci>`

(4,2)`first (+3) (1,2)`

`ghci>`

('a',True)`second odd ('a',1)`

(Indeed, we already encountered
`second`

, in the section called “JSON typeclasses without overlapping instances”.) We can use
`first`

to golf our definition of
`randomsIO`

, turning it into a
one-liner.

-- file: ch15/RandomGolf.hs import Control.Arrow (first) randomsIO_golfed :: Random a => IO [a] randomsIO_golfed = getStdRandom (first randoms . split)

In the previous section, we saw how to hide the fact that we're using a State monad to hold the state for our Supply monad.

Another important way to make code more modular involves
separating its *interface*—what the
code can do—from its
*implementation*—how it does
it.

The standard random number generator in
`System.Random`

is known to be quite slow. If we use
our `randomsIO`

function to provide it with
random numbers, then our `next`

action will
not perform well.

One simple and effective way that we could deal with this is to provide Supply with a better source of random numbers. Let's set this idea aside, though, and consider an alternative approach, one that is useful in many settings. We will separate the actions we can perform with the monad from how it works using a typeclass.

-- file: ch15/SupplyClass.hs class (Monad m) => MonadSupply s m | m -> s where next :: m (Maybe s)

This typeclass defines the interface that any supply monad must implement. It bears careful inspection, since it uses several unfamiliar Haskell language extensions. We will cover each one in the sections that follow.

How should we read the snippet ```
MonadSupply s
m
```

in the typeclass? If we add parentheses, an
equivalent expression is `(MonadSupply s) m`

, which
is a little clearer. In other words, given some type variable
`m`

that is a Monad, we can make
it an instance of the typeclass MonadSupply s.
unlike a regular typeclass, this one has a
*parameter*.

As this language extension allows a typeclass to
have more than one parameter, its name is
`MultiParamTypeClasses`

. The parameter
`s`

serves the same purpose as the
Supply type's parameter of the same name: it
represents the type of the values handed out by the
`next`

function.

Notice that we don't need to mention `(>>=)`

or
`return`

in the definition of MonadSupply s,
since the type class's context (superclass) requires that a
MonadSupply s must already be a
Monad.

To revisit a snippet that we ignored earlier, ```
| m
-> s
```

is a *functional
dependency*, often called a
*fundep*. We can read the vertical bar
`|`

as “such that”, and the arrow
`->`

as “uniquely determines”. Our
functional dependency establishes a
*relationship* between `m`

and `s`

.

The availability of functional dependencies is governed by
the `FunctionalDependencies`

language pragma.

The purpose behind us declaring a relationship is to help the type checker. Recall that a Haskell type checker is essentially a theorem prover, and that it is conservative in how it operates: it insists that its proofs must terminate. A non-terminating proof results in the compiler either giving up or getting stuck in an infinite loop.

With our functional dependency, we are telling the type
checker that every time it sees some monad
`m`

being used in the context of a
MonadSupply s, the type `s`

is
the only acceptable type to use with it. If we were to omit
the functional dependency, the type checker would simply give
up with an error message.

It's hard to picture what the relationship between
`m`

and `s`

really means, so
let's look at an instance of this typeclass.

-- file: ch15/SupplyClass.hs import qualified Supply as S instance MonadSupply s (S.Supply s) where next = S.next

Here, the type variable `m`

is replaced
by the type S.Supply s. Thanks to our functional
dependency, the type checker now knows that when it sees a
type S.Supply s, the type can be used as an
instance of the typeclass MonadSupply s.

If we didn't have a functional dependency, the type checker would not be able to figure out the relationship between the type parameter of the class MonadSupply s and that of the type Supply s, and it would abort compilation with an error. The definition itself would compile; the type error would not arise until the first time we tried to use it.

To strip away one final layer of abstraction, consider the
type S.Supply Int. Without a functional
dependency, we could declare this an instance of
MonadSupply s. However, if we tried to write
code using this instance, the compiler would not be able to
figure out that the type's Int parameter needs to
be the same as the typeclass's `s`

parameter, and it would report an error.

Functional dependencies can be tricky to understand, and once we move beyond simple uses, they often prove difficult to work with in practice. Fortunately, the most frequent use of functional dependencies is in situations as simple as ours, where they cause little trouble.

If we save our typeclass and instance in a source file
named `SupplyClass.hs`

, we'll need to add
a module header such as the following.

-- file: ch15/SupplyClass.hs {-# LANGUAGE FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses #-} module SupplyClass ( MonadSupply(..) , S.Supply , S.runSupply ) where

The `FlexibleInstances`

extension is necessary
so that the compiler will accept our instance declaration.
This extension relaxes the normal rules for writing instances
in some circumstances, in a way that still lets the compiler's
type checker guarantee that it will terminate. Our need for
`FlexibleInstances`

here is caused by our use of
functional dependencies, but the details are unfortunately
beyond the scope of this book.

Finally, notice that we're re-exporting the
`runSupply`

and Supply names
from this module. It's perfectly legal to export a name from
one module even though it's defined in another. In our case,
it means that client code only needs to import the
`SupplyClass`

module, without also importing the
`Supply`

module. This reduces the number of
“moving parts” that a user of our code needs to
keep in mind.

Here is a simple function that fetches two values from our Supply monad, formats them as a string, and returns them.

-- file: ch15/Supply.hs showTwo :: (Show s) => Supply s String showTwo = do a <- next b <- next return (show "a: " ++ show a ++ ", b: " ++ show b)

This code is tied by its result type to our Supply monad. We can easily generalize to any monad that implements our MonadSupply interface by modifying our function's type. Notice that the body of the function remains unchanged.

-- file: ch15/SupplyClass.hs showTwo_class :: (Show s, Monad m, MonadSupply s m) => m String showTwo_class = do a <- next b <- next return (show "a: " ++ show a ++ ", b: " ++ show b)

The State monad lets us plumb a piece of
mutable state through our code. Sometimes, we would like to be
able to pass some *immutable* state around,
such as a program's configuration data. We could use the
State monad for this purpose, but we could then
find ourselves accidentally modifying data that should remain
unchanged.

Let's forget about monads for a moment and think about what
a *function* with our desired characteristics
ought to do. It should accept a value of some type `e`

(for *environment*)
that represents the data
that we're passing in, and return a value of some
other type `a`

as its result. The
overall type we want is e -> a.

To turn this type into a convenient Monad
instance, we'll wrap it in a `newtype`

.

-- file: ch15/SupplyInstance.hs newtype Reader e a = R { runReader :: e -> a }

Making this into a Monad instance doesn't take much work.

-- file: ch15/SupplyInstance.hs instance Monad (Reader e) where return a = R $ \_ -> a m >>= k = R $ \r -> runReader (k (runReader m r)) r

We can think of our value of type `e`

as an *environment*
in which we're evaluating some expression. The `return`

action
should have the same effect no matter what the environment is,
so our version ignores its environment.

Our definition of `(>>=)`

is a little more complicated, but
only because we have to make the environment—here the
variable `r`

—available both in the
current computation and in the computation we're chaining
into.

How does a piece of code executing in this monad find out
what's in its environment? It simply has to
`ask`

.

-- file: ch15/SupplyInstance.hs ask :: Reader e e ask = R id

Within a given chain of actions, every invocation of
`ask`

will return the same value, since the
value stored in the environment doesn't change. Our code
is easy to test in **ghci**.

`ghci>`

Loading package old-locale-1.0.0.0 ... linking ... done. Loading package old-time-1.0.0.0 ... linking ... done. Loading package random-1.0.0.0 ... linking ... done. 6`runReader (ask >>= \x -> return (x * 3)) 2`

The Reader monad is included in the standard
`mtl`

library, which is usually bundled with GHC.
You can find it in the `Control.Monad.Reader`

module.
The motivation for this monad may initially seem a little thin,
because it is most often useful in complicated code. We'll
often need to access a piece of configuration information
deep in the bowels of a program; passing that information in as
a normal parameter would require a painful restructuring of our
code. By hiding this information in our monad's plumbing,
intermediate functions that don't care about the configuration
information don't need to see it.

The clearest motivation for the
Reader monad will come in Chapter 18, *Monad transformers*, when we discuss
combining several monads to build a new monad. There, we'll see
how to gain finer control over state, so that our code can
modify some values via the State monad, while other
values remain immutable, courtesy of the Reader
monad.

Now that we know about the Reader
monad, let's use it to create an instance of our
MonadSupply typeclass. To keep our example simple,
we'll violate the spirit of MonadSupply here: our
`next`

action will always return the same
value, instead of always returning a different value.

It would be a bad idea to directly make the
Reader type an instance of the
MonadSupply class, because then
*any* Reader could act as a
MonadSupply. This would usually not make any
sense.

Instead, we create a `newtype`

based on
Reader. The `newtype`

hides the fact that we're
using Reader internally. We must now make our type
an instance of both of the typeclasses we care about. With the
`GeneralizedNewtypeDeriving`

extension enabled, GHC
will do most of the hard work for us.

-- file: ch15/SupplyInstance.hs newtype MySupply e a = MySupply { runMySupply :: Reader e a } deriving (Monad) instance MonadSupply e (MySupply e) where next = MySupply $ do v <- ask return (Just v) -- more concise: -- next = MySupply (Just `liftM` ask)

Notice that we must make our type an instance of MonadSupply e, not MonadSupply. If we omit the type variable, the compiler will complain.

To try out our MySupply type, we'll first create a simple function that should work with any MonadSupply instance.

-- file: ch15/SupplyInstance.hs xy :: (Num s, MonadSupply s m) => m s xy = do Just x <- next Just y <- next return (x * y)

If we use this with our Supply monad and
`randomsIO`

function, we get a different
answer every time, as we expect.

`ghci>`

-15697064270863081825448476392841917578`(fst . runSupply xy) `fmap` randomsIO`

`ghci>`

17182983444616834494257398042360119726`(fst . runSupply xy) `fmap` randomsIO`

Because our MySupply monad has two layers of
`newtype`

wrapping, we can make it easier to use by writing a
custom execution function for it.

-- file: ch15/SupplyInstance.hs runMS :: MySupply i a -> i -> a runMS = runReader . runMySupply

When we apply our `xy`

action
using this execution function, we get the same answer every
time. Our code remains the same, but because we are executing
it in a different implementation of MonadSupply,
its behavior has changed.

`ghci>`

4`runMS xy 2`

`ghci>`

4`runMS xy 2`

Like our MonadSupply typeclass and
Supply monad, almost all of the common Haskell
monads are built with a split between interface and
implementation. For example, the `get`

and
`put`

functions that we introduced as
“belonging to” the State monad are
actually methods of the MonadState typeclass; the
State type is an instance of this class.

Similarly, the standard Reader monad is an
instance of the MonadReader typeclass, which
specifies the `ask`

method.

While the separation of interface and implementation that
we've discussed above is appealing for its architectural
cleanliness, it has important practical applications that will
become clearer later. When we start combining monads in Chapter 18, *Monad transformers*, we will save a lot of effort through the use of
`GeneralizedNewtypeDeriving`

and typeclasses.

The blessing and curse of the IO monad is that it is extremely powerful. If we believe that careful use of types helps us to avoid programming mistakes, then the IO monad should be a great source of unease. Because the IO monad imposes no restrictions on what we can do, it leaves us vulnerable to all kinds of accidents.

How can we tame its power? Let's say that we would like to guarantee to ourselves that a piece of code can read and write files on the local filesystem, but that it will not access the network. We can't use the plain IO monad, because it won't restrict us.

Let's create a module that provides a small set of functionality for reading and writing files.

-- file: ch15/HandleIO.hs {-# LANGUAGE GeneralizedNewtypeDeriving #-} module HandleIO ( HandleIO , Handle , IOMode(..) , runHandleIO , openFile , hClose , hPutStrLn ) where import System.IO (Handle, IOMode(..)) import qualified System.IO

Our first approach to creating a restricted version of
IO is to wrap it with a `newtype`

.

-- file: ch15/HandleIO.hs newtype HandleIO a = HandleIO { runHandleIO :: IO a } deriving (Monad)

We do the by-now familiar trick of exporting the type
constructor and the `runHandleIO`

execution
function from our module, but not the data constructor. This
will prevent code running within the HandleIO
monad from getting hold of the IO monad that it
wraps.

All that remains is for us to wrap each of the actions we want our monad to allow. This is a simple matter of wrapping each IO with a HandleIO data constructor.

-- file: ch15/HandleIO.hs openFile :: FilePath -> IOMode -> HandleIO Handle openFile path mode = HandleIO (System.IO.openFile path mode) hClose :: Handle -> HandleIO () hClose = HandleIO . System.IO.hClose hPutStrLn :: Handle -> String -> HandleIO () hPutStrLn h s = HandleIO (System.IO.hPutStrLn h s)

We can now use our restricted HandleIO monad to perform I/O.

-- file: ch15/HandleIO.hs safeHello :: FilePath -> HandleIO () safeHello path = do h <- openFile path WriteMode hPutStrLn h "hello world" hClose h

To run this action, we use
`runHandleIO`

.

`ghci>`

[1 of 1] Compiling HandleIO ( HandleIO.hs, interpreted ) Ok, modules loaded: HandleIO.`:load HandleIO`

`ghci>`

Loading package old-locale-1.0.0.0 ... linking ... done. Loading package old-time-1.0.0.0 ... linking ... done. Loading package filepath-1.1.0.0 ... linking ... done. Loading package directory-1.0.0.0 ... linking ... done. Loading package mtl-1.1.0.0 ... linking ... done.`runHandleIO (safeHello "hello_world_101.txt")`

`ghci>`

`:m +System.Directory`

`ghci>`

`removeFile "hello_world_101.txt"`

If we try to sequence an action that runs in the HandleIO monad with one that is not permitted, the type system forbids it.

`ghci>`

<interactive>:1:36: Couldn't match expected type `HandleIO a' against inferred type `IO ()' In the second argument of `(>>)', namely `removeFile "goodbye"' In the first argument of `runHandleIO', namely `(safeHello "goodbye" >> removeFile "goodbye")' In the expression: runHandleIO (safeHello "goodbye" >> removeFile "goodbye")`runHandleIO (safeHello "goodbye" >> removeFile "goodbye")`

There's one small, but significant, problem with our HandleIO monad: it doesn't take into account the possibility that we might occasionally need an escape hatch. If we define a monad like this, it is likely that we will occasionally need to perform an I/O action that isn't allowed for by the design of our monad.

Our purpose in defining a monad like this is to make it easier for us to write solid code in the common case, not to make corner cases impossible. Let's thus give ourselves a way out.

The `Control.Monad.Trans`

module defines a
“standard escape hatch”, the MonadIO
typeclass. This defines a single function,
`liftIO`

, which lets us embed an
IO action in another monad.

`ghci>`

`:m +Control.Monad.Trans`

`ghci>`

class (Monad m) => MonadIO m where liftIO :: IO a -> m a -- Defined in Control.Monad.Trans instance MonadIO IO -- Defined in Control.Monad.Trans`:info MonadIO`

Our implementation of this typeclass is trivial: we just wrap IO with our data constructor.

-- file: ch15/HandleIO.hs import Control.Monad.Trans (MonadIO(..)) instance MonadIO HandleIO where liftIO = HandleIO

With judicious use of `liftIO`

, we can
escape our shackles and invoke IO actions where
necessary.

-- file: ch15/HandleIO.hs tidyHello :: FilePath -> HandleIO () tidyHello path = do safeHello path liftIO (removeFile path)

The disadvantage of hiding IO in another monad is that we're still tied to a concrete implementation. If we want to swap HandleIO for some other monad, we must change the type of every action that uses HandleIO.

As an alternative, we can create a typeclass that specifies the interface we want from a monad that manipulates files.

-- file: ch15/MonadHandle.hs {-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses #-} module MonadHandle (MonadHandle(..)) where import System.IO (IOMode(..)) class Monad m => MonadHandle h m | m -> h where openFile :: FilePath -> IOMode -> m h hPutStr :: h -> String -> m () hClose :: h -> m () hGetContents :: h -> m String hPutStrLn :: h -> String -> m () hPutStrLn h s = hPutStr h s >> hPutStr h "\n"

Here, we've chosen to abstract away both the type of the monad and the type of a file handle. To satisfy the type checker, we've added a functional dependency: for any instance of MonadHandle, there is exactly one handle type that we can use. When we make the IO monad an instance of this class, we use a regular Handle.

-- file: ch15/MonadHandleIO.hs {-# LANGUAGE FunctionalDependencies, MultiParamTypeClasses #-} import MonadHandle import qualified System.IO import System.IO (IOMode(..)) import Control.Monad.Trans (MonadIO(..), MonadTrans(..)) import System.Directory (removeFile) import SafeHello instance MonadHandle System.IO.Handle IO where openFile = System.IO.openFile hPutStr = System.IO.hPutStr hClose = System.IO.hClose hGetContents = System.IO.hGetContents hPutStrLn = System.IO.hPutStrLn

Because any MonadHandle must also be a
Monad, we can write code that manipulates files
using normal `do`

notation, without caring what monad it will
finally execute in.

-- file: ch15/SafeHello.hs safeHello :: MonadHandle h m => FilePath -> m () safeHello path = do h <- openFile path WriteMode hPutStrLn h "hello world" hClose h

Because we made IO an instance of this type
class, we can execute this action from **ghci**.

`ghci>`

Loading package old-locale-1.0.0.0 ... linking ... done. Loading package old-time-1.0.0.0 ... linking ... done. Loading package filepath-1.1.0.0 ... linking ... done. Loading package directory-1.0.0.0 ... linking ... done. Loading package mtl-1.1.0.0 ... linking ... done.`safeHello "hello to my fans in domestic surveillance"`

`ghci>`

`removeFile "hello to my fans in domestic surveillance"`

The beauty of the typeclass approach is that we can swap one underlying monad for another without touching much code, as most of our code doesn't know or care about the implementation. For instance, we could replace IO with a monad that compresses files as it writes them out.

Defining a monad's interface through a typeclass has a
further benefit. It lets other people hide our implementation
in a `newtype`

wrapper, and automatically derive instances of
just the typeclasses they want to expose.

In fact, because our `safeHello`

function doesn't use the IO type, we can even use
a monad that *can't* perform I/O. This
allows us to test code that would normally have side effects
in a completely pure, controlled environment.

To do this, we will create a monad that doesn't perform I/O, but instead logs every file-related event for later processing.

-- file: ch15/WriterIO.hs data Event = Open FilePath IOMode | Put String String | Close String | GetContents String deriving (Show)

Although we already developed a Logger type
in the section called “Using a new monad: show your work!”, here we'll use the
standard, and more general, Writer monad. Like
other `mtl`

monads, the API provided by
Writer is defined in a typeclass, in this case
MonadWriter. Its most useful method is
`tell`

, which logs a value.

`ghci>`

`:m +Control.Monad.Writer`

`ghci>`

tell :: (MonadWriter w m) => w -> m ()`:type tell`

The values we log can be of any Monoid type. Since the list type is a Monoid, we'll log to a list of Event.

We could make Writer [Event] an instance of MonadHandle, but it's cheap, easy, and safer to make a special-purpose monad.

-- file: ch15/WriterIO.hs newtype WriterIO a = W { runW :: Writer [Event] a } deriving (Monad, MonadWriter [Event])

Our execution function simply removes the `newtype`

wrapper we added, then calls the normal Writer
monad's execution function.

-- file: ch15/WriterIO.hs runWriterIO :: WriterIO a -> (a, [Event]) runWriterIO = runWriter . runW

When we try this code out in **ghci**, it gives us a log of
the function's file activities.

`ghci>`

[1 of 3] Compiling MonadHandle ( MonadHandle.hs, interpreted ) [2 of 3] Compiling SafeHello ( SafeHello.hs, interpreted ) [3 of 3] Compiling WriterIO ( WriterIO.hs, interpreted ) Ok, modules loaded: SafeHello, MonadHandle, WriterIO.`:load WriterIO`

`ghci>`

((),[Open "foo" WriteMode,Put "foo" "hello world",Put "foo" "\n",Close "foo"])`runWriterIO (safeHello "foo")`

The writer monad uses the monoid's
`mappend`

function every time we use
`tell`

. Because
`mappend`

for lists is
`(++)`

, lists are not a good practical
choice for use with Writer: repeated appends are
expensive. We use lists above purely for
simplicity.

In production code, if you want to use the
Writer monad and you need list-like behaviour,
use a type with better append characteristics. One such type
is the difference list, which we introduced in the section called “Taking advantage of functions as data”. You don't need to roll your own
difference list implementation: a well tuned library is
available for download from Hackage, the Haskell package
database. Alternatively, you can use the Seq
type from the `Data.Sequence`

module, which we
introduced in the section called “General purpose sequences”.

If we use the typeclass approach to restricting IO, we may still want to retain the ability to perform arbitrary I/O actions. We might try adding MonadIO as a constraint on our typeclass.

-- file: ch15/MonadHandleIO.hs class (MonadHandle h m, MonadIO m) => MonadHandleIO h m | m -> h instance MonadHandleIO System.IO.Handle IO tidierHello :: (MonadHandleIO h m) => FilePath -> m () tidierHello path = do safeHello path liftIO (removeFile path)

This approach has a problem, though: the added MonadIO constraint loses us the ability to test our code in a pure environment, because we can no longer tell whether a test might have damaging side effects. The alternative is to move this constraint from the typeclass, where it “infects” all functions, to only those functions that really need to perform I/O.

-- file: ch15/MonadHandleIO.hs tidyHello :: (MonadIO m, MonadHandle h m) => FilePath -> m () tidyHello path = do safeHello path liftIO (removeFile path)

We can use pure property tests on the functions that lack MonadIO constraints, and traditional unit tests on the rest.

Unfortunately, we've substituted one problem for another: we can't invoke code with both MonadIO and MonadHandle constraints from code that has the MonadHandle constraint alone. If we find that somewhere deep in our MonadHandle-only code, we really need the MonadIO constraint, we must add it to all the code paths that lead to this point.

Allowing arbitrary I/O is risky, and has a profound effect on how we develop and test our code. When we have to choose between being permissive on the one hand, and easier reasoning and testing on the other, we usually opt for the latter.