In Haskell, here's a monad that combines the State and Maybe monads:
type StatefulMaybe a = StateT Int Maybe a
This is a computation that can succeed (returning a value) or fail. If it succeeds, it carries a state along with the returned value.
I'd like to write a function
choice :: StatefulMaybe a -> StatefulMaybe a -> StatefulMaybe a
that takes two such computations and returns the first one (if any) that succeeds. Only state changes by the successful computation are carried forward.
In fact after some experimentation I figured out how to write this. Here it is:
orMaybe :: Maybe a -> Maybe a -> Maybe a
orMaybe (Just x) _ = Just x
orMaybe Nothing x = x
choice :: StatefulMaybe a -> StatefulMaybe a -> StatefulMaybe a
choice mx my = StateT (\s ->
(runStateT mx s) `orMaybe` (runStateT my s)
)
It works:
foo :: StatefulMaybe String
foo = do
modify (+ 20)
fail "didn't succeed"
baz :: StatefulMaybe String
baz = do
modify (+ 30)
return "two"
bar :: StatefulMaybe String
bar = do
s <- choice foo baz
return (s ++ " done")
> runStateT bar 0
Just ("two done",30)
My question is this: Is there some easier or more natural way to write this choice function than my implementation above? In particular, is there some way I can lift the orMaybe
function into my monad?
orMaybe
ismplus
fromMonadPlus
-- I think usingmplus
instead ofchoice
should work, too. – Boeke