一般主題:雖然我發現將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
引入的任何剛性結構)?