我知道如何使用do
块内每个monad的函数。但是一旦我完成了如何运行计算并获得结果?
run :: (MonadError Error m, MonadState State m) => m Int -> Int
run = ???
答案 0 :(得分:5)
mtl
的重点是你没有指定具体的monad变换器堆栈 - 你只需指定它必须处理错误并保持状态。
但是,一旦你真的想要运行这个动作,你做需要把自己绑在一个特定的monad变换器堆栈上。该堆栈将告知您如何“运行”您的monadic动作。在您的情况下,您可能希望使用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
请注意,此不是您可以做出的具体堆栈的唯一选择。事实上,你甚至可以交换State
和Except
的顺序,并选择StateT State (Either Error)
作为你的monad!
runAction :: State -> -- initial state
Either Error Int -- account for possibility of error
runAction initialState = evalState action initialState
mtl
对堆栈中monad的 order 一无所知这一事实是其缺点之一(也是有些人更喜欢坚持使用{{1}的原因之一}})。