我正在尝试编写一个简单的函数来安全地读取文件(如果它存在)并且如果文件不存在则什么都不做:
safeRead :: String -> IO ()
safeRead path = readFile path `catch` handleExists
where handleExists e
| isDoesNotExistError e = return ()
| otherwise = throwIO e
这在编译时失败
Couldn't match type ‘[Char]’ with ‘()’
Expected type: IO ()
Actual type: IO String
In the first argument of ‘catch’, namely ‘readFile path’
In the expression: readFile path `catch` handleExists
这是有道理的,因为:t readFile
is readFile :: FilePath -> IO String
。例如返回的函数IO String
(并且IO String
与 不同IO ()
)
将签名更改为String -> IO String
Couldn't match type ‘()’ with ‘[Char]’
Expected type: IOError -> IO String
Actual type: IOError -> IO ()
In the second argument of ‘catch’, namely ‘handleExists’
In the expression: readFile path `catch` handleExists
这也是有道理的,因为 handleExists 有类型IO ()
为了节省大家的查找,catch 被导入:
import Control.Exception
catch 的签名是:
catch :: Exception e => IO a -> (e -> IO a) -> IO a
我真正的问题是,如何在 Haskell 中编写这种错误安全、灵活的代码?更具体地说,我必须对这个函数做出什么改变才能让它同时处理成功案例和失败案例?