Reputation: 2273
I know how to use functions from each monad inside a do
block. But once i'm finished how do I run the computation and get the result?
run :: (MonadError Error m, MonadState State m) => m Int -> Int
run = ???
Upvotes: 2
Views: 392
Reputation: 32319
The whole point of mtl
is that you don't specify your concrete monad transformer stack - you just specify that it has to handle errors and hold state.
However, once you actually want to run this action, you do need to tie yourself down to a particular monad transformer stack. That stack will inform how you can "run" your monadic action. In your case, it looks like you probably want to go with ExcepT Error (State State)
:
action :: (MonadError Error m, MonadState State m) => m Int
action = undefined
runAction :: State -> -- initial state
Either Error Int -- account for possibility of error
runAction initialState = evalState (runExceptT action) initialState
Note that this isn't the only choice of a concrete stack you could have made. In fact, you could even swap the order of the State
and Except
and choose StateT State (Either Error)
as your monad!
runAction :: State -> -- initial state
Either Error Int -- account for possibility of error
runAction initialState = evalState action initialState
The fact that mtl
says nothing about the order of monads in your stack is one of its shortcomings (and one of the reasons why some people prefer to just stick with transformers
).
Upvotes: 6