How do I write writeFile with any data type?
I have a function that takes some arguments and returns IO (Either String String)
, say
testEither :: Int -> IO (Either String String)
testEither 0 = return (Left "we got an error")
testEither _ = return (Right "everything is ok")
(The real function extracts some things from the real world and may fail)
I want to send the output of this function to writeFile fileName
. Expected Behavior: If I bind testEither 0
to writeFile "test.txt"
, I fail with Left ...
, and if I call it with testEither 1
, I get everything is ok
in a file test.txt
.
I am guessing that the type of the entire expression should be something like IO (Either String ())
, but I could be wrong.
source to share
You can use ErrorT 1 monad transformer to give you clean error handling on top of the 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
1ErrorT
appears to have been replaced with ExceptT
in the newest version mtl
, but the functionality should be similar.
source to share
This won't happen automatically, but you can easily use pattern matching to accomplish this:
writeFileEither :: FilePath -> Either a String -> IO ()
writeFileEither _ (Left _) = return ()
writeFileEither fp (Right text) = writeFile fp text
Then you can link them together with
main = testEither 1 >>= writeFileEither "test.txt"
Or with the designation:
main = do
result <- testEither 1
writeFileEither "test.txt" result
source to share
Below is a function main
that shows how to use testEither
in IO
: if it testEither
returns an error then the error is written to stderr
otherwise the correct result is fetched from Right
and written to a file test.txt
:
import System.IO testEither :: Int → IO (Either String String) testEither 0 = return (Left "we got an error") testEither _ = return (Right "everything is ok") main :: IO 𐌏 main = do res ← testEither 0 case res of Left err → hPutStrLn stderr ("Error: " ++ err) Right s → writeFile "test.txt" s
source to share