[Haskell-cafe] Stacking monads

Andrew Coppin andrewcoppin at btinternet.com
Fri Oct 3 13:39:08 EDT 2008

David Menendez wrote:
> On Thu, Oct 2, 2008 at 3:40 PM, Andrew Coppin
> <andrewcoppin at btinternet.com> wrote:
>> David Menendez wrote:
>>> You could try using an exception monad transformer here
>> I thought I already was?
> No, a monad transformer is a type constructor that takes a monad as an
> argument and produces another monad. So, (ErrorT ErrorType) is a monad
> transformer, and (ErrorT ErrorType m) is a monad, for any monad m.

Right, OK.

> If you look at the type you were using, you see that it breaks down into
> (Either ErrorType) (ResultSet State), where Either ErrorType :: * -> *
> and ResultSet State :: *. Thus, the monad is Either ErrorType. The
> fact that ResultSet is also a monad isn't enough to give you an
> equivalent to (>>=), without one of the functions below.

OK, that makes sense.

>> Uh... what's Applicative? (I had a look at Control.Applicative, but it just
>> tells me that it's "a strong lax monoidal functor". Which isn't very
>> helpful, obviously.)
> Applicative is a class of functors that are between Functor and Monad
> in terms of capabilities. Instead of (>>=), they have an operation
> (<*>) :: f (a -> b) -> f a -> f b, which generalizes Control.Monad.ap.

(As an aside, Control.Monad.ap is not a function I've ever heard of. It 
seems simple enough, but what an unfortunate name...!)

> The nice thing about Applicative functors is that they compose.
> With monads, you can't make (Comp m1 m2) a monad without a function
> analogous to inner, outer, or swap.

So I see. I'm still not convinced that Applicative helps me in any way 

> From your code examples, it isn't clear to me that applicative
> functors are powerful enough, but I can't really say without knowing
> what you're trying to do.

The whole list-style "multiple inputs/multiple outputs" trip, basically.

> The fact that the functions you gave take a
> state as an argument and return a state suggests that things could be
> refactored further.

If you look at run_or, you'll see that this is _not_ a simple state 
monad, as in that function I run two actions starting from _the same_ 
initial state - something which, AFAIK, is impossible (or at least very 
awkward) with a state monad.

Really, it's a function that takes a state and generates a new state, 
but it may also happen to generate *multiple* new states. It also 
consumes a Foo or two in the process.

More information about the Haskell-Cafe mailing list