G-J*_*G-J 4 error-handling file-io haskell handler
我正在尝试为函数添加一个简单的处理程序readFile:
readHandler :: IOError -> IO ()
readHandler e
| isDoesNotExistError e = putStrLn "The file does not exist"
| otherwise = putStrLn "Something went wrong"
main = do
// stop executing if there is no file
contents <- (readFile "path.xml") `catch` readHandler
// generates [(x,y),(x,y)]
coordinates = parseXML contents
// I want to do something with the coordinates
nextFunction coordinates
Run Code Online (Sandbox Code Playgroud)
当我尝试编译这个时,我收到错误:
Couldn't match type `()' with `[Char]'
Expected type: IOError -> IO String
Actual type: IOError -> IO ()
In the second argument of `catch', namely `readHandler'
In a stmt of a 'do' block:
contents <- (readFile "path") `catch` readHandler
In the expression:
do { contents <- (readFile "path") `catch` readHandler;
putStrLn contents }
Run Code Online (Sandbox Code Playgroud)
因此,readHandler :: IOError -> IO ()应该是readHandler :: IOError -> IO String.
但这种方式我无法打印错误信息.
我该如何解决这个问题?
应该是什么类型的catch (readFile "path") readHandler?
显然,如果文件存在,我们希望它是一个String,catch不应该改变它的类型,所以无论如何我们必须产生一个String无论如何.因为如果抛出异常,readHandler运行它也必须产生一个字符串.
这种方式catch就像一个非常复杂的if表达式:)但是,它不太理想,因为我们不想继续运行我们的函数与一些String不是来自文件的随机.
相反,我们可以做类似的事情
main = handle readHandler $ do
...
Run Code Online (Sandbox Code Playgroud)
从现在开始,我们只需要制作一个IO (),琐碎的.
如果由于某种原因这不能漂浮你的船,另一个理智的选择是将这个令人不快的例外转变为更愉快 Either
main = do
strOrExc <- try $ readFile "foo"
case strOrExc of
Left except -> print except
Right contents -> putStrLn contents
Run Code Online (Sandbox Code Playgroud)
当然,你可以Exception e => Either e a用任何方式处理这个带给你快乐的事情.
当然还有最后的选择,让整个程序在当时和那里戛然而止.我们可以通过改变来做到这一点readHandler
import System.Exit
readHandler :: IOError -> IO a
readHandler = putStrLn "Buckle your seatbelts" >> exitFailure
Run Code Online (Sandbox Code Playgroud)