のドキュメントControl.Monad.Trans.Error
は、2 つのモナドを結合するこの例を提供します。
type ErrorWithIO e a = ErrorT e IO a
==> ErrorT (IO (Either e a))
これは直観に反していると思います:ラッピングErrorT
していると思われますが、エラー情報がIO アクションの結果の型に挿入されているように見えます。私はそれを期待していただろう IO
==> ErrorT (Either e (IO a))
「ラップ」という言葉の通常の意味に基づいています。
問題をさらに混乱させるためにStateT
、それぞれのいくつかを実行します。
type MyError e = ErrorT e Identity -- (see footnote)
type StateWithError s e a = StateT s (MyError e) a
==> StateT (s -> ErrorT (Either e (a, s)))
の側に状態型s
が注入されていますが、全体も関数でラップされています。Either
Right
Either
モナドが逆に結合されている場合、事態をさらに混乱させるために:
type ErrorWithState e s a = ErrorT e (State s) a
==> ErrorT (StateT (s -> (Either e a, s)))
「外側」はまだ関数です。Either e (s -> (a, s))
状態関数がエラー型内にネストされているようなものは生成されません。
これらすべてに根底にある論理的な一貫性があることは確かですが、よくわかりません。その結果、個々のモナドの意味を理解するのに問題がなくても、あるモナドを別のモナドと組み合わせることが何を意味するのかを考えるのは難しいと思います。
誰かが私を啓発できますか?
(脚注:説明のために、とが互いに一致するように構成ErrorT
しています。通常は、レイヤーを使用するだけで済みます。Identity
StateWithError
ErrorWithState
StateWithError s e a = StateT s (Either e) a
ErrorT