Haskell MTL:如何退出monad并获取其中的值?

use*_*376 1 monads haskell typeclass state-monad monad-transformers

我知道如何使用do块内每个monad的函数.但是一旦我完成了如何运行计算并获得结果?

run :: (MonadError Error m, MonadState State m) => m Int -> Int
run = ???
Run Code Online (Sandbox Code Playgroud)

Ale*_*lec 5

重点mtl是你没有指定具体的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
Run Code Online (Sandbox Code Playgroud)

请注意,这不是您可以制作的具体堆栈的唯一选择.事实上,你甚至可以交换的顺序StateExcept与选择StateT State (Either Error)为您的单子!

runAction :: State ->           -- initial state
             Either Error Int   -- account for possibility of error
runAction initialState = evalState action initialState
Run Code Online (Sandbox Code Playgroud)

事实上mtl没有说明堆栈中monad 的顺序是它的缺点之一(也是有些人喜欢坚持的原因之一transformers).

  • @ user47376 尝试扩展新类型。你会看到 `ExceptT e (State s) a ~ State s (Either ea) ~ s -> (Either ea, s)` 而 `StateT s (Except e) a ~ s -> 除 e (a, s) ) ~ s -> e (a, s)`。前者让错误处理程序可以访问发生错误时的状态值,尽管 [`catch` 的标准实现](https://hackage.haskell.org/package/transformers-0.5.4.0/docs/ src/Control.Monad.Trans.State.Lazy.html#liftCatch) 不这样做。 (2认同)