これは Monad Transformers との私の最初の知り合いなので、答えは明白かもしれません。
StateT MyMonad MyType 型の do ブロック内にいるとしましょう。同じ型の別の関数で状態を変更し、MyMonad MyType 型の値を返すようにしたいとします。どうすればそれを達成できますか?ここの例はguessSessionでそれを示していると思いますが、それを適用する方法を理解できないようです!
これは Monad Transformers との私の最初の知り合いなので、答えは明白かもしれません。
StateT MyMonad MyType 型の do ブロック内にいるとしましょう。同じ型の別の関数で状態を変更し、MyMonad MyType 型の値を返すようにしたいとします。どうすればそれを達成できますか?ここの例はguessSessionでそれを示していると思いますが、それを適用する方法を理解できないようです!
モナド変換子で基礎となるモナドを使用したい場合は、次を使用できますlift
。
lift :: (MonadTrans t, Monad m) => m a -> t m a
この場合、t
はStateT MyState
、m
は ですMyMonad
。たとえば、次のようになります。
foo :: StateT MyState MyMonad MyType
foo = do
modify $ \s -> s+1
lift $ doSomethingInMyMonad 42
MyMonad MyType
モナドトランスフォーマーは、内部から型の値を返すという意味で「階層化」されていません。それはより文字通りの変換です:それらはモナドを、変換されたモナドでアクションを実行する能力を持つ新しいものに変えます。StateT s m
したがって、通常のState s
モナドと考えることができますが、 を使用lift
してターン アクションを でアクションにm
変換することもできますStateT s m
。
、 などの標準のMonad Transformer Library (mtl)トランスフォーマーを使用している場合は、実際に;を使用する必要はありません。スタックのどこかに適切なトランスフォーマーを持つモナドで機能します。(スタックは、 のような変換されたモナドの単なるタワーです。)StateT
ReaderT
lift
modify
ask
StateT s (ReaderT r IO)
さらに、一番下に大きなスタックがある場合は、アクションを任意の数のレイヤーIO
に持ち上げるための便利な関数があります。IO
liftIO :: (MonadIO m) => IO a -> m a
、、などで動作liftIO (putStrLn "Hello, world!")
します。IO
StateT Int IO
ContT r (WriterT [String] IO)
(追記として、これfoo
は実際には関数ではありません。より正確な用語は、アクションまたは計算です。)