一般主题:虽然我发现将monad堆叠在一起的想法非常有吸引力,但我在绘制代码的执行方式方面遇到很多麻烦,以及运行这些图层的适当命令是什么。下面是一个堆栈的例子:Writer,State,State和Error,没有特定的顺序(或者是否存在?)。您如何推断monadT堆栈中函数的执行顺序?
-----------------------
-- Utility Functions --
-----------------------
type Memory = Map String Int
type Counter = Int
type Log = String
tick :: (MonadState Counter m) => m()
tick = modify (+1)
record :: (MonadWriter Log m) => Log -> m()
record msg = tell $ msg ++ "; "
------------------
-- MonadT Stack --
------------------
mStack :: (MonadTrans t, MonadState Memory m, MonadState Counter (t m), MonadError ErrMsg (t m), MonadWriter Log (t m)) => t m Int
mStack = do
tick
m <- lift get
let x = fromJust (M.lookup "x" m) in x
record "accessed memory"
case True of
True -> return 100
False -> throwError "false"
请注意mStack
,是否有错误被抛出与否无关的功能的任何其他部分。
现在非常想输出看起来像这样:
(Right 100, 1, "accessed memory", fromList [...])
或一般:
(output of errorT, output of stateT Counter, output of writerT, output of StateT Memory)
但我无法得到它的工作。具体地讲,我试图运行堆栈仿佛错误是在最外层上:
mem1 = M.fromList [("x",10),("y",5)]
runIdentity $ runWriterT (runStateT (runStateT (runErrorT mStack) 0) mem1) ""
但正在此错误消息:
Couldn't match type `Int' with `Map [Char] Int'
上述实例之外,在一般情况下,当我我打电话:
runMonadT_1 (runMonadT_2 expr param2) param1
,
是与01的功能先运行,然后将输出传送到与monadT_1
相关的功能?换句话说,与代码在上面的函数mStack
中看起来一样,执行的顺序完全取决于monadT的运行顺序(除了由lift
引入的任何刚性结构)?