2012-01-20 20 views
5

これは私の最初のモナドトランスフォーマーとの知り合いです。モナド内部モナド変換器の結果

私はStateT MyMonad MyType型のdoブロックの中にいるとしましょう。同じ型の別の関数が状態を変更してMyMonad MyType型の値を返すようにしたいとします。それをどうすれば実現できますか?私は例をhere guessSessionでそれを表示すると思うが、私はそれを適用する方法を理解できないようです!

+1

ます。http:// www.haskell.org/hoogle – jberryman

答えて

9

あなたがモナド変換子に根本的なモナドを使用する場合は、liftを使用することができますが、この場合には

lift :: (MonadTrans t, Monad m) => m a -> t m a 

tStateT MyStateあり、そしてmMyMonadです。したがって、たとえば:

foo :: StateT MyState MyMonad MyType 
foo = do 
    modify $ \s -> s+1 
    lift $ doSomethingInMyMonad 42 

モナド変圧器を使用すると、内部からタイプMyMonad MyTypeの値を返すだろうという意味で「上に積層」されていません。より多くのリテラルの変形です:彼らは変形されたモナドでアクションを実行する能力を持つ新しいものにモナドを回します。だからStateT s mを普通のState sモナドと考えることができますが、を使用してmの行動をStateT s mに実行することができます。

あなたがなどStateTReaderT、などの標準Monad Transformer Library(MTL)変圧器を使用している場合は、実際にliftを使用する必要はありません。 modifyaskのようなものは、のモナドで動作し、スタックのどこかに正しいトランスフォーマがあります。 (スタックはStateT s (ReaderT r IO)のように、変換されたモナドのほんの塔です。)

また、あなたが底にIOを持つ大規模なスタックを持っている場合は、任意の数の層をIOアクションを持ち上げる便利な機能があります:

liftIO :: (MonadIO m) => IO a -> m a 

のでIOliftIO (putStrLn "Hello, world!")作品、StateT Int IO、その上ContT r (WriterT [String] IO)、と。

(追加のノート、fooとしてここでは実際には関数ではありません。より正確な用語はアクションまたは計算です。)あなたがhoogleについて知らない場合には

+0

私は理解していると思います。ただ完全にはっきりするために。 StateTを追加する前にdoSomethingInMyMonad 42を実行したとします。今私は< - リフト$ doSomethingInMyMonad 42を行う。正しい? – aelguindy

+0

@aelguindy:うん! 'MyMonad'だけを使用するコードセクションがある場合は、doブロック全体を持ち上げることもできます:' lift $ do ... '。 – ehird

+0

ありがとう!これが正しい場所であるかどうかはわかりませんが、2つの引数lift2を使用して持ち上げることはできますか? *ばかげた質問!*答えを見つけた – aelguindy

関連する問題