Compiler errors ";“处理”;函数与真实世界Haskell
我在读RWH,我已经读到了第九章。它介绍了以下代码:Compiler errors ";“处理”;函数与真实世界Haskell,compiler-errors,haskell,Compiler Errors,Haskell,我在读RWH,我已经读到了第九章。它介绍了以下代码: import System.IO import Control.Exception saferFileSize :: FilePath -> IO (Maybe Integer) saferFileSize path = handle (\_ -> return Nothing) $ do h <- openFile path ReadMode size <- hFileSize h hClose h
import System.IO
import Control.Exception
saferFileSize :: FilePath -> IO (Maybe Integer)
saferFileSize path = handle (\_ -> return Nothing) $ do
h <- openFile path ReadMode
size <- hFileSize h
hClose h
return (Just size)
import System.IO
导入控制。异常
安全文件大小::文件路径->IO(可能是整数)
saferFileSize路径=句柄(\ \ \->不返回任何内容)$do
h不返回任何内容)
$do{hRWH相当旧。在GHC6.10左右的版本中,handle
函数签名已更改
要使用旧版本,请导入Control.OldException
而不是Control.Exception`。您将收到弃用警告,但程序将编译
或者,您可以使用新接口并为处理程序提供显式签名,如下所示:
((\ _ -> return Nothing) :: IOException -> IO (Maybe Integer))
RWH发布后不久,异常接口被更改为支持更灵活的处理程序,处理程序的类型决定了它将捕获哪些异常。例如,接受SomeException
的处理程序将捕获任何异常(通常不是一个好主意),而接受IOException
的处理程序将只捕获IO异常
因此,使用“不做任何事情”处理程序(如示例中的处理程序)很容易遇到歧义问题,因为编译器无法推断您试图捕获的异常类型。解决此问题的简单方法是为处理程序函数提供类型签名
handle ((\_ -> return Nothing) :: IOException -> IO (Maybe Integer)) $ do ...
不过,这可能有点冗长。另一种解决方案是专门化句柄
handleIO :: (IOException -> IO a) -> IO a -> IO a
handleIO = handle
然后,只要想处理IO异常,就可以使用handleIO
,而不必详细说明处理程序的类型签名
saferFileSize path = handleIO (\_ -> return Nothing) $ do ...
第三个选项是使用ScopedTypeVariables
扩展,该扩展(除其他外)允许您仅为函数的参数提供类型注释,允许推断其余的类型
{-# LANGUAGE ScopedTypeVariables #-}
saferFileSize path = handle (\(_ :: IOException) -> return Nothing) $ do ...
Haskell网站上的handle
函数的文档对此非常不清楚(至少对于入门级人员——需要文档的人!),感谢您非常清楚的解释,编译器只需要我们指定要处理的异常类型!
{-# LANGUAGE ScopedTypeVariables #-}
saferFileSize path = handle (\(_ :: IOException) -> return Nothing) $ do ...