I would like to add to MoFu's answer that if you have MaybeT IO , you can use the full power of your MonadPlus instance. For example, if you need to verify that a condition is met, use guard or mfilter . Therefore, you can write:
import Control.Monad import Control.Monad.IO.Class import Control.Monad.Trans import Control.Monad.Trans.Maybe getAnswer :: (MonadPlus m, MonadIO m) => String -> m String getAnswer expected = mfilter (== expected) $ liftIO getLine
This type is very common, it works for any monad that is MonadPlus and MonadIO . This is convenient if you decide to change your monad stack later. But we could also use a more specific type (MonadIO m) => String -> MaybeT m String .
To extract the MaybeT IO value from your internal calculation, I would suggest writing a variant fromMaybe for MaybeT :
fromMaybeT :: (Monad m) => ma -> MaybeT ma -> ma fromMaybeT onFail = maybe onFail return <=< runMaybeT
It retrieves the result using runMaybeT . If it is Just , just return it, otherwise do the onFail action.
Together we get:
main = fromMaybeT (putStrLn "nope") $ do a <- getAnswer "a" b <- getAnswer a liftIO $ putStrLn "correct!"
Petr pudlák
source share