带有 IO 和 Maybe 的 Monad 转换器

Monad transformers with IO and Maybe

我正在尝试堆叠 IO 和 Maybe monad,但要么我对 monad 转换器了解不够透彻,要么使用转换器无法做到这一点。有人可以帮助我理解这一点吗?

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

在上面的简化示例中,我有一个函数 f returns 和 Maybe String,我想在 IO 做块。我试过了

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

这让我可以在 do 块的第二行中提取 Maybe String,但我需要从中提取字符串。有没有办法不使用 case 来做到这一点?

让我们稍等一下您的第一个片段。如果f input是一个Maybe String,而你想把它的结果传递给writeFile "out.txt",它取一个String,你需要处理f input的可能性正在 Nothing。您不必从字面上使用案例陈述。例如:

    Prelude中的
  • maybe是案例分析打包成一个函数;

  • fromMaybe from Data.Maybe 让您轻松提供默认值,如果这对您的用例有意义的话;

  • 来自 Data.Foldable
  • traverse_ and for_ 可用于静默忽略 Nothing-ness:

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

不过,无论您选择做什么,都需要以某种方式处理 Nothing

至于 MaybeT,您真的不需要 monad 转换器。 MaybeT IO 适用于当您需要类似 Maybe 计算但您还可以在其中包含 IO 计算的情况。如果 f :: String -> Maybe String 已经完成了您想要的操作,则无需向其添加基础 IO 层。