mtlパッケージはモナド変換子を実装していません。少なくとも WriterT は から再エクスポートさtransformersれたばかりです。
transformersパッケージWriterTは、モナドトランスフォーマー自体である を実装します。Writer単なるエイリアスです:
type Writer w = WriterT w Identity
一部のライブラリはWriter個別に実装できますが、とにかくそれはWriterT. (Identityは自明なモナドであり、追加の動作はありません。)
MonadTrans基礎となるモナドを変換されたものにラップすることができます。これがなくても問題はありませんが、手動でラッピングを行う必要があります (方法については、MonadTransインスタンス定義を参照WriterTしてください)。本当に必要な唯一の使用例MonadTrans- 変圧器の実際のタイプがわからない場合。
MonadWriterで宣言された型クラスmtlです。そのメソッド ( writer、pass、tellおよびlisten) は function for と同じですWriterT。WriterTスタック内のトランスフォーマーの正確なタイプ (さらには数も!) がわからない場合でも、トランスフォーマーのスタックを介して(自動的に!) 計算をラップできます。
したがって、WriterT「必須」の唯一のタイプです。
他のモナドトランスフォーマーについても同じです:BaseTはトランスフォーマーでBaseあり、基礎となるモナドを持たないモナドでMonadBaseあり、型クラスBaseT(トランスフォーマースタックのどこかにあるすべてのモナドのクラス) です。
追加した:
RWHの本で素晴らしい説明を見つけることができます
以下に基本的な例を示します。
import Control.Monad.Trans
import Control.Monad.Trans.Writer
import Control.Monad.Trans.Reader hiding (ask)
-- `ask` from transformers
-- ask :: Monad m => ReaderT r m r
import qualified Control.Monad.Trans.Reader as TransReader (ask)
-- `ask` from mtl
-- ask :: MonadReader r m => m r
import qualified Control.Monad.Reader as MtlReader (ask)
-- Our monad transformer stack:
-- It supports reading Int and writing String
type M m a = WriterT String (ReaderT Int m) a
-- Run our monad
runM :: Monad m => Int -> M m a -> m (a, String)
runM i action = runReaderT (runWriterT action) i
test :: Monad m => M m Int
test = do
tell "hello"
-- v <- TransReader.ask -- (I) will not compile
v1 <- lift TransReader.ask -- (II) ok
v2 <- MtlReader.ask -- (III) ok
return (v1 + v2)
main :: IO ()
main = runM 123 test >>= print
(I)コンパイラによって拒否されることに注意してください(エラーメッセージを確認してみてください!)。しかし、 (「明示的なリフティング」)(II)のおかげでコンパイルされます。MonadTransのおかげでMonadReader、(III)すぐに使用できます (「暗黙のリフティング」)。どのように機能するかについては、RWH の本をお読みください。
(この例ではask、2 つの異なるモジュールからインポートするため、修飾されたインポートが必要です。通常は、一度に 1 つのみを使用します。)
また、特に質問するつもりはありませんでしたWriter。
よくわかりません... Reader、Stateおよび他の人が同じスキーマを使用しています。に置き換えるWriterとState、 の説明が表示されStateます。