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?
If I understand the question correctly, I think that this function already exists: <|>:
bar :: StatefulMaybe String
bar = do
s <- foo <|> baz
return (s ++ " done")
The <|>
function is part of the Applicative
type class, of which StateT
is an instance when the inner monad is both a Functor
and MonadPlus
instance, which is true for Maybe
.
*Q66992923> runStateT bar 0
Just ("two done",30)
As luqui suggests in the comment, I think that mplus
ought to work, too, since the default implementation of mplus
is <|>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With