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
ます。