【发布时间】: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 中的
<-并没有从 monad 中提取值。相反,它只是让你像你可以提取它一样工作。例如,如果您在Maybedo-block 中有x <- m,那么您可以使用 do 块的其余部分来指定使用x执行的操作 如果m不是 @987654338 @。如果m原来是Nothing,并且可能性仍然存在,那么将没有x可以使用,并且故障将相应地通过>>=传播。
标签: haskell monad-transformers maybe io-monad