
David Menendez wrote:
On Thu, Oct 2, 2008 at 3:40 PM, Andrew Coppin
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 though...
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.