前回のモナド変換子に、さらにIOを乗せて(敷いて?)みます。
putStrLnとかが使えるようになります。
import Control.Monad.State import Control.Monad.Trans.Maybe push :: Show a => a -> StateT [a] (MaybeT IO) () push x = do xs <- get put (x:xs) lift $ lift $ putStrLn $ "push " ++ show x pop :: Show a => StateT [a] (MaybeT IO) a pop = do (x:xs) <- get put xs lift $ lift $ putStrLn $ "pop " ++ show x return x main = runMaybeT $ (`runStateT` [1,10,100]) $ do push 3 pop push 2
実行結果です。
> main push 3 pop 3 push 2 Just ((),[2,1,10,100]) >
うまくいっていますね。
空のstackにpopした場合は、
> runMaybeT $ (`runStateT` []) $ do { pop; } Nothing
前回同様、自動的にNothingになりました。
強制的にNothingにする場合は、
lift $ return Nothing
じゃなくて、(これだと何も起こらない)
lift $ fail ""
とすれば良いです。