简体   繁体   中英

Monad transformers with IO and Maybe

I am trying to stack up IO and Maybe monads but either I don't understand monad transformers well enough or this is not possible using transformers. Can some one help me understand this?

f :: String -> Maybe String

main :: IO ()
main = do
  input <- getLine            -- IO String
  output <- f input           -- Maybe String (Can't extract because it is IO do block)
  writeFile "out.txt" output  -- gives error because writeFile expects output :: String

In the above simplified example, I have a function f that returns a Maybe String and I would like to have a neat way of extracting this in the IO do block. I tried

f :: String -> MaybeT IO String

main :: IO ()
main = do
  input <- getLine              -- IO String
  output <- runMaybeT (f input) -- Extracts output :: Maybe String instead of String
  writeFile "out.txt" output    -- gives error because writeFile expects output :: String

which lets me extract the Maybe String out in the second line of do block but I need to extract the string out of that. Is there a way to do this without using case ?

Let's stick for a moment with your first snippet. If f input is a Maybe String , and you want to pass its result to writeFile "out.txt" , which takes a String , you need to deal with the possibility of f input being Nothing . You don't have to literally use a case-statement. For instance:

  • maybe from the Prelude is case analysis packaged as a function;

  • fromMaybe from Data.Maybe lets you easily supply a default value, if that makes sense for your use case;

  • traverse_ and for_ from Data.Foldable could be used to silently ignore Nothing -ness:

     for_ (f input) (writeFile "out.txt") -- Does nothing if `f input` is `Nothing`. 

Still, no matter what you choose to do, it will involve handling Nothing somehow.

As for MaybeT , you don't really want monad transformers here. MaybeT IO is for when you want something like a Maybe computation but in which you can also include IO computations. If f :: String -> Maybe String already does what you want, you don't need to add an underlying IO layer to it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM