At different questions I've found hints in comments concerning using the (->)
instance of Monads e.g. for realizing point-free style.
As for me, this is a little too abstract. Ok, I've seen Arrow instances on (->)
and it seems to me, that (->)
can be used in instance notations but not in type declarations (that would alone be stuff for another question).
Has anyone examples using (->)
as instance of Monad? Or a good link?
Sorry if this question may already have been discussed here, but searching for "(->)
Monad instance" gives you many many hits as you can imagine ... since nearly every question about Haskell somewhere involves (->)
or "Monad".
For a given type r
, the function of type r -> a
can be thought of as a computation delivering an a
using an environment typed r
. Given two functions r -> a
and a -> (r -> b)
, it's easy to imagine that one can compose these when given an environment (again, of type r
).
But wait! That's exactly what monads are about!
So we can create an instance of Monad for (->) r
(*) that implements f >>= g
by passing the r
to both f
and g
. This is what the Monad instance for (->) r
does.
To actually access the environment, you can use id :: r -> r
, which you can now think of as a computation running in an environment r
and delivering an r
. To create local sub-environments, you can use the following:
inLocalEnvironment :: (r -> r) -> (r -> a) -> (r -> a)
inLocalEnvironment xform f = \env -> f (xform env)
This pattern of having an environment passed to computations that can then query it and modify it locally is useful for not just the (->) r
monad, which is why it is abstracted into the MonadReader
class, using much more sensible names than what I've used here:
http://hackage.haskell.org/packages/archive/mtl/2.0.1.0/doc/html/Control-Monad-Reader-Class.html
Basically, it has two instances: (->) r
that we've seen here, and ReaderT r m
, which is just a newtype
wrapper around r -> m a
, so it's the same thing as the (->) r
monad I've described here, except it delivers computations in some other, transformed monad.
(*) (->) r
might look funny at first, but this is Haskell syntax for partially applying the two-parameter type constructor (->)
to the first type argument r
, i.e. it means something like r -> _
with the second argument not yet given. So (->) r a
(or ((->) r) a
) is the same as r -> a
.