[Haskell-beginners] Are monads pure?

Stephen Tetley stephen.tetley at gmail.com
Tue May 18 04:24:17 EDT 2010


On 18 May 2010 05:37, Amy de Buitléir <amy at nualeargais.ie> wrote:

[SNIP]
>> [aditya siram]
>> With a monad you can
>> 1. takes some data and wraps it up in a type (return) :
>> a -> m a
>> 2. apply a function to the data within the type (>>=).
>> m a -> (a -> m b) -> m b
>
>
> But if that's all you need to do, you could just use an Applicative Functor,
> right? The picture I have at the moment is:
>
> Functors can apply a function to a value inside a container.
>
> Applicative functors provide pure expressions and sequencing, but no
> binding. All applicative functors are also functors.

Hello all


With bind, monads are a more powerful than applicative functors as
they give you the ability to perform context sensitive operations
whereas you could consider Applicative functors to be "context-free".

This means you can write more control operations for monads than
applicative functors, for instance you can have a State applicative
functor just as you can have a State monad. However with just
applicative you can't write the useful bracket function, which first
takes a snapshot of the state, performs the stateful function, then
restores the original state:


> newtype State st a = State { getStateF :: st -> (a,st) }


Functor instance:

> instance Functor (State st) where
>   fmap f (State sf) = State $ \st ->
>                         let (a,st1) = sf st in (f a,st1)

Applicative instance

> instance Applicative (State st) where
>   pure a = State $ \st -> (a,st)
>   (State sfab) <*> (State sf) = State $ \st ->
>                                 let (fab,st1) = sfab st
>                                     (a,  st2) = sf st1
>                                 in (fab a,st2)

Monad instance

> instance Monad (State st) where
>   return a = State $ \st -> (a,st)
>   (State sf) >>= smf = State $ \st ->
>                           let (a1,st1) = sf st1
>                               sfun     = getStateF (smf a1)
>                               (a2,st2) = sfun st2
>                           in (a2,st2)


> get :: State a a
> get = State $ \st -> (st,st)

> put :: a -> State a a
> put a = State $ \ _st -> (a,a)


> mbracket :: State st a -> State st a
> mbracket ma = do { st  <- get
>                  ; ans <- ma
>                  ; put st
>                  ; return ans
>                  }

Or without the do notation:

> mbracket' :: State st a -> State st a
> mbracket' ma = get    >>= \st  ->
>                ma     >>= \ans ->
>                put st >>= \_   -> return ans

No bracket with just the applicative machinery...


More information about the Beginners mailing list