我正在尝试堆叠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
有没有办法做到这一点?
让我们用你的第一个片段坚持一下。如果f input
是Maybe String
,并且你想将其结果传递给需要writeFile "out.txt"
的String
,你需要处理f input
成为Nothing
的可能性。您不必逐字地使用case语句。例如:
maybe
案例分析打包为一个函数;fromMaybe
的Data.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
图层。