【问题标题】:Monad transformers with IO and Maybe带有 IO 和 Maybe 的 Monad 转换器
【发布时间】:2019-04-27 01:01:00
【问题描述】:

我正在尝试堆叠 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,它返回一个Maybe String,我想有一种巧妙的方法在IO do 块中提取它。我试过了

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 的情况下做到这一点?

【问题讨论】:

  • 你为什么要在这里使用 monad 转换器?
  • @Carl 我搜索了在 do 块中使用两种类型的 monad(我理解这是不可能的),并发现一些线程建议使用 lift 和 monad 转换器。我对 monad 转换器了解不多,所以把它当作一个学习的时刻。仍然不确定在这里使用是否正确。
  • 那么当f 返回Nothing 时,你希望发生什么?
  • 我实际上不确定什么是最好的方法。我可以抛出一个错误而不写入文件,在这种情况下我必须使用case 语句,所以我想这有点回答我的问题?
  • 一个值得强调的细节是 do-block 中的 &lt;- 并没有从 monad 中提取值。相反,它只是让你像你可以提取它一样工作。例如,如果您在Maybe do-block 中有x &lt;- m,那么您可以使用 do 块的其余部分来指定使用 x 执行的操作 如果 m 不是 @987654338 @。如果m 原来是Nothing,并且可能性仍然存在,那么将没有x 可以使用,并且故障将相应地通过&gt;&gt;= 传播。

标签: haskell monad-transformers maybe io-monad


【解决方案1】:

让我们坚持一下您的第一个 sn-p。如果f input 是Maybe String,并且你想将它的结果传递给writeFile "out.txt",它接受String,你需要处理f input 是Nothing 的可能性。您不必从字面上使用案例陈述。例如:

  • Prelude 中的maybe 是打包为函数的案例分析;

  • 来自Data.Maybe 的fromMaybe 可让您轻松提供默认值(如果这对您的用例有意义);

  • traverse_ 和来自Data.Foldable 的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 -&gt; Maybe String 已经做了你想做的事,你不需要添加底层IO 到它。

【讨论】:

  • 感谢您的解释。我不知道 fromMaybe 这实际上对我的问题有意义。
  • @Carl 发现得很好。我已将其添加到答案中;谢谢。
  • @Carl omg DUH traverse_ 为此。我总是发明自己的组合器来做同样的事情。需要记住Maybe 是一个“集合”。谢谢。
猜你喜欢
  • 2017-12-06
  • 2021-11-27
  • 2017-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-29
  • 1970-01-01
相关资源
最近更新 更多