Pao*_*tti 3 io monads haskell types exception-handling
我正在尝试loadFile在Haskell中实现一个安全功能,该功能可以捕获任何异常并产生a,Maybe String但以下实现无法编译
import System.IO (readFile)
import Control.Exception (catch, IOException)
-- readFile :: FilePath -> IO String
-- this compiles good
safeReadFile :: FilePath -> IO (Either IOException String)
safeReadFile p =
(Right <$> readFile p) `catch`
(\e -> pure $ Left e)
-- this does not!
safeReadFile' :: FilePath -> IO (Maybe String)
safeReadFile' p =
(Just <$> readFile p) `catch`
(\e -> pure Nothing)
Run Code Online (Sandbox Code Playgroud)
有人可以解释为什么GCH提出以下问题吗?
Ambiguous type variable ‘e0’ arising from a use of ‘catch’
prevents the constraint ‘(GHC.Exception.Exception
e0)’ from being solved.
Probable fix: use a type annotation to specify what ‘e0’ should be.
These potential instances exist:
instance GHC.Exception.Exception IOException
-- Defined in ‘GHC.IO.Exception’
...plus 20 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
Run Code Online (Sandbox Code Playgroud)
如何在e变量上应用必要的类型注释?Haskell文档没有任何提示:-(
您必须指定要捕获的异常类型。safeLoadFile明确提及IOException,而safeLoadFile'没有提及。
尝试以下方法:
safeLoadFile' :: FilePath -> IO (Maybe String)
safeLoadFile' p =
(Just <$> loadFile p) `catch`
((\e -> pure Nothing) :: IOException -> IO (Maybe String))
Run Code Online (Sandbox Code Playgroud)
或者找到一些类似的方法来注释变量的类型e。例如(\ (e :: IOException) -> ...),如果打开,也可以使用ScopedTypeVariables。
另一个选择:
safeLoadFile' :: FilePath -> IO (Maybe String)
safeLoadFile' p = (Just <$> loadFile p) `catch` handler
where
handler :: IOException -> IO (Maybe String)
handler _ = pure Nothing
Run Code Online (Sandbox Code Playgroud)