I have a RWST in haskell over a Maybe, which short circuits under certain conditions. I want to run this action until it returns Nothing, and get the last Just. So my situation is as follows;
type St = MyState
type Re = MyRead
type Wr = MyWriter
type Foo = RWST Re Wr St Maybe
action :: Foo ()
The only way that I thought of for achieving that, is by defining the following;
run = action >> run <|> action
which has the downside that if the short circuiting happens on the first second run, even though there is an output, I get Nothing because run runs the action twice. Is there any better way of looping? I looked into extra but the functions supplied there do not help my cause.
So, after considering the answers given, and trying everything out, it seems the easiest solution is to use many. In the general case though, swapping for a MaybeT as suggested is a better solution.
I've been looking over your question and going back and forth about whether this answer applies to your situation. Really I can't tell without more context, so I'll just leave it here in case.
You are using
Maybeas the base monad, and that might not be what you want. I want to forget about the reader and writer part ofRWSTfor a moment and pretend we are just usingStateT, because it simpler, but the same idea applies (StateTis basically the same thing asRWST () ()after all). The definition ofStateTis:So, after all is unrolled and done, the type of
runends up asYou give it an
St, and it gives you back either a pair with a resultingStin it, orNothing. In particular, when it "fails" (as in, returnsNothing), the failure does not come with a resulting state, so all state changes prior to the failure are forgotten. That means if you ever take the right side of(<|>), anything that happened in the left side doesn't matter anymore, the only influence it has on the result is the fact that it failed. But the fact that you want to do this in a loop betrays that you want to keep the state changes after failure.That is what
MaybeTis for. Put theMaybeTon the outside.MaybeTis defined asSo if your monad were
MaybeT (State St), the implementation type would beNotice that now, whether the action succeeds or fails, we get an
Stout the other end. This will allow(<|>)to carry on manipulating the state that its left side changed rather than starting anew, which I'm guessing is your intention (though I can't say for sure).In general, the inner monads of a transformer chain are more powerful -- a transformer are always subject to the rules of their inner monad. The "primary" effect of
StateT s Maybeis that it either succeeds with a value or fails outright, and then the statefulness has to be "emulated" on top of that. Whereas the primary effect ofMaybeT (State s)is that of statefulness -- no matter whatMaybeTdoes, there is always a single state carried through the computation. More on transformer stack design here.