Introduction

Some very brief notes summarizing Haskell’s ((->) r) monad. It’s my crib sheet, written partly to straighten matters in my own mind and partly for future reference.

Most of the information here comes from the usual places, notably the Typeclassopedia.1 I’m also indebted to Dominic Prior for many helpful discussions. Dominic is collecting useful and interesting monad examples2 on Google Docs.

The ((->) r) monad

If you use GHC, the ((->) r) instance is defined in GHC-Base3 these days:

instance Monad ((->) r) where
    return = const
    x >>= f = \r -> f (x r) r

or,

    (x >>= f) r = f (x r) r

To seasoned Haskell programmers, I expect the ((->) r) instance is obvious, but it took me a while to get a feel for it. In particular we’re talking about functions from r, the type parameter of the monad, to some other type.

In the definition of x >>= f I often think of x as akin to a value, and f to a function. Let’s see what types they have in this instance:

x :: m a
f :: a -> m b

x ::      r -> a
f :: a -> r -> b

So both x and f are functions, with an argument of type r which permeates everything.

As is often the case, the Kleisli arrow elucidates matters:

(f >=> g)     = \x -> f x >>= g
              = \x -> (\r -> g (f x r) r)

or,

(f >=> g) x r = g (f x r) r

Or in words: every time you evaluate a function, pass an extra r argument. Within a set of functions the value of this argument stays the same, so it provides a constant evaluation environment.

One could use this as a more civilized version of global variables.

If we now revisit >>= it makes more sense:

(x >>= f) r = f (x r) r

To evaluate the right-hand side, first evaluate x in the context of r to give x', then evaluate f of x' again in the context of r.

Let’s turn to return. We know this should be the most direct translation of a non-monadic value into the monad: here that translates to being a value which doesn’t depend on the environment.

return x e = x

This is a standard function though: it’s just const.

If we wanted to be rigorous, we would show that these definitions for >>= and return do indeed form a monad i.e. that they satisfy the monad laws.

fmap

Every monad is a functor, and so given >>= we can deduce fmap:

fmap f x = x >>= return . f

Specialize to ((->) r):

fmap f x r = (x >>= (const . f)) r
           = (const . f) (x r) r
           = const (f (x r)) r
           = f (x r)
           = (f.x) r

Here though, the types are enough to suggest the solution:

fmap :: Functor f => (a -> b) -> f a -> f b
fmap :: (a -> b) -> (f -> a) -> (f -> b)
fmap = (.)

join

Given our ‘just add an extra argument’ intuition, join is obvious:

join x r = x r r

here x is doubly-wrapped, has type m (m a), and so needs two copies of the extra argument.

If one wants to be rigorous:

join x r = (x >>= id) r
         = (id (x r) r)
         = (x r) r
         = x r r

Going the other way is perhaps more useful because it derives >>= from the more intuitive join (assuming you accept the definition of fmap):

(x >>= f) r = join (fmap f x) r
            = join (f.x) r
            = (f.x) r r
            = f (x r) r

An example

Consider this code:

incN :: Enum a => a -> Int -> a
incN c n = toEnum $ n + fromEnum c

decN c n = incN c (-n)

inc2N c n = incN c (2 * n)

incN just increments an enumerable thing n times, decN decrements it, and inc2N increments it 2n times:

*Main> incN ’a’ 3
’d’
*Main> inc2N ’a’ 3
’g’
*Main> decN ’m’ 3
’j’

We can compose these functions easily with the Kleisli arrow:

*Main> (incN >=> inc2N >=> decN) ’a’ 0
’a’					
*Main> (incN >=> inc2N >=> decN) ’a’ 1	
’c’					
*Main> (incN >=> inc2N >=> decN) ’a’ 2
’e’

Here the character value gets threaded through the functions, whilst the same integer environment is seen throughout. I say seen, but actually it’s all invisible: the monad implicitly supplies the context variable, so we don’t need to worry about it.

Alternatively, in do-notation, given:

munge c = do
             x <- incN  c
             y <- inc2N x
             z <- decN  y
             return z

We can say:

*Main> munge ’a’ 2
’e’

An arithmetic amusement

It’s quite nice to ponder this:

join (+) 2

From the discussion above:

join (+) 2 = (+) 2 2 = 2 + 2 = 4

Perhaps more interestingly if we join - we can calculate the additive identity.

join (-) x = (-) x x = 0

Here x doesn’t matter so in a loose sense (ignoring types)

join (-) ≈ const 0

The type caveat is just that

Prelude Control.Monad> :t join (-)
join (-) :: Num a => a -> a

but

Prelude Control.Monad> :t const 0
const 0 :: Num a => b -> a

In other words the true const takes anything to an arbitrary zero, but the join version takes any number to a zero of the same type. Surely this is still useful for some sort of obfuscation though ?

Perhaps the multiplicative identity is more useful:

join div 42 = 1

The Applicative ((->) r)

Given a monad instance we can always make an Applicative too. Here:

instance Applicative ((->) a) where
   pure = const
   (f <*> x) e = (f e) (x e)

Again we can see the pattern that inside the applicative we first evaluate things in a fixed context, and then operate with them as normal. However, here it makes better to sense to think of everything as a function which takes a single parameter: the environment.

As usual if we make everything pure it just works as normal:

*Main> (pure (,) <*> pure ’a’ <*> pure ’b’) 2
(’a’,’b’)

Or more idiomatically with <$>:

*Main> ((,) <$> pure ’a’ <*> pure ’b’) 2
(’a’,’b’)

Now it’s easy to let any of the terms access the context, and we can use the incN function from above:

*Main> ((,) <$> incN ’a’ <*> pure ’b’) 2
(’c’,’b’)
*Main> ((,) <$> pure ’a’ <*> incN ’b’) 2
(’a’,’d’)

We can also see the context from the ‘function’:

*Main> ((\x y z -> (x,y,z)) <*> incN ’a’ <*> pure ’b’) 2
(2,’c’,’b’)

The Reader Monad

In practice, people don’t use the naked ((->) r) monad when they they want to provide a constant context. Instead, they use Reader.4

Under the covers, this is basically the same animal, but it’s a bit nicer to use. A full discussion of Reader needs a new article though.