拥有IO和Maybe的Monad变形金刚

问题描述 投票:0回答:1

我正在尝试堆叠IO和Maybe monads,但要么我不太了解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

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

haskell monad-transformers maybe io-monad
1个回答
4
投票

让我们用你的第一个片段坚持一下。如果f inputMaybe String,并且你想将其结果传递给需要writeFile "out.txt"String,你需要处理f input成为Nothing的可能性。您不必逐字地使用case语句。例如:

  • 来自Prelude的maybe案例分析打包为一个函数;
  • 来自fromMaybeData.Maybe可让您轻松提供默认值,如果这对您的用例有意义的话;
  • 来自traverse_for_Data.Foldable可以用来默默地忽略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图层。

© www.soinside.com 2019 - 2024. All rights reserved.