一般的なテーマ:モナドを積み重ねるというアイデアは非常に魅力的ですが、コードの実行方法や層を実行するための適切な命令は何かを思い描いています。以下は、スタックの1つの例です:Writer、State、State、およびError(順序は特にありません)?モナドTスタック内の関数の実行順序についてはどう思いますか?
-----------------------
-- 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
にコードのように必須の命令は、モダードTが実行される順序に完全に依存する実行順序です(構造内の剛性を除いて、lift
によって導入されました)。