如何用任何一种数据类型组合writeFile?

时间:2014-08-25 14:46:14

标签: haskell

我有一个函数接受一些参数并返回IO (Either String String),比如说

testEither :: Int -> IO (Either String String)
testEither 0 = return (Left "we got an error")
testEither _ = return (Right "everything is ok")

(真实函数从现实世界中获取一些东西并可能失败)

我想将该函数的输出发送到writeFile fileName。预期的行为:如果我将testEither 0绑定到writeFile "test.txt",则会导致Left ...失败,如果我使用testEither 1调用它,我会在文件{{everything is ok中找到test.txt 1}}。

我猜整个表达式的类型应该类似IO (Either String ()),但我可能错了。

4 个答案:

答案 0 :(得分:3)

使用Either Traversable实例

可以轻松实现
import Data.Traversable

main = do
    traverse (writeFile "test.txt") (Left "we got an error")
    traverse (writeFile "test.txt") (Right "everything is ok")

答案 1 :(得分:3)

您可以使用ErrorT 1 monad转换器在IO monad之上为您提供纯错误处理:

import Control.Monad.Error

testEither :: Int -> IO (Either String String)
testEither 0 = return (Left "we got an error")
testEither _ = return (Right "everything is ok")

main = runErrorT $ do
    result <- ErrorT $ testEither 0
    lift $ writeFile "test.txt" result

1 ErrorT似乎已在mtl的最新版本中替换为ExceptT,但功能应该类似。

答案 2 :(得分:1)

这不会自动发生,但您可以轻松地使用模式匹配来执行此操作:

writeFileEither :: FilePath -> Either a String -> IO ()
writeFileEither _  (Left _) = return ()
writeFileEither fp (Right text) = writeFile fp text

然后你可以用

将它们绑定在一起
main = testEither 1 >>= writeFileEither "test.txt"

或者用符号表示:

main = do
    result <- testEither 1
    writeFileEither "test.txt" result

答案 3 :(得分:0)

下面的main函数是一个示例,说明如何在testEither中使用IO:如果testEither返回错误,则会将错误写入{{1}否则从stderr中提取正确的结果并将其写入文件Right

test.txt