异常#
简介#
Haskell 中的某些类型,如
Maybe
和Either
能够处理部分运算异常,但不够强大;Haskell 函数是无副作用的,因此异常处理在 I/O 操作部分更有意义;
纯代码部分同样可以抛出异常;
Prelude> 4 `div` 0 *** Exception: divide by zero
因为纯代码部分的状态是透明的,因此异常只能在 I/O 操作部分捕获;
应尽量保持 I/O 操作部分代码最小化,利用 Haskell 的类型系统避免异常;
捕获#
-
System.IO.Error.
catchIOError
:: IO a -> (IOError -> IO a) -> IO a# 若 I/O 操作抛出异常,则将异常传入异常处理函数,并返回处理结果。
在
base-4.4.0.0
之前,该函数名为catch
。IOError
类型表示 I/O 操作异常,带有异常信息,该类型的实现取决于语言的实际实现。1import System.Environment 2import System.IO 3import System.IO.Error 4 5main = toTry `catchIOError` handler 6 7-- | 程序的核心。 8-- 计算文件有多少行。 9toTry :: IO () 10toTry = do (fileName : _) <- getArgs 11 contents <- readFile fileName 12 let lnum = show . length . lines $ contents 13 putStrLn $ "The file has " ++ lnum ++ " lines!" 14 15-- | 处理 'IOError'。 16-- 若打开文件时出现异常,则打印信息。 17handler :: IOError -> IO () 18handler _ = putStrLn "Exception!"
-
GHC.IO.Exception.
ioError
:: IOError -> IO a# 将捕获的异常重新抛出。
-
System.IO.Error.
isAlreadyExistsError
:: IOError -> Bool#
-
System.IO.Error.
isAlreadyInUseError
:: IOError -> Bool#
-
System.IO.Error.
isDoesNotExistError
:: IOError -> Bool#
-
System.IO.Error.
isEOFError
:: IOError -> Bool#
-
System.IO.Error.
isFullError
:: IOError -> Bool#
-
System.IO.Error.
isIllegalOperation
:: IOError -> Bool#
-
System.IO.Error.
isPermissonError
:: IOError -> Bool#
-
System.IO.Error.
isResourceVanishedError
:: IOError -> Bool#
-
System.IO.Error.
isUserError
:: IOError -> Bool# 判断异常是否为对应异常。
1import System.Environment 2import System.IO 3import System.IO.Error 4 5main = toTry `catchIOError` handler 6 7-- | 程序的核心。 8-- 计算文件有多少行。 9toTry :: IO () 10toTry = do (fileName : _) <- getArgs 11 contents <- readFile fileName 12 let lnum = show . length . lines $ contents 13 putStrLn $ "The file has " ++ lnum ++ " lines!" 14 15-- | 处理 'IOError'。 16-- 若有已知异常,则发出警告,否则抛出。 17handler :: IOError -> IO () 18handler e | isDoesNotExistError e = putStrLn "No such file!" 19 | isFullError e = putStrLn "Disk full!" 20 | isIllegalOperation e = putStrLn "Illegal move!" 21 | otherwise = ioError e
-
System.IO.Error.
ioeGetErrorString
:: IOError -> String#
-
System.IO.Error.
ioeGetErrorType
:: IOError -> IOErrorType#
-
System.IO.Error.
ioeGetFileName
:: IOError -> Maybe FilePath#
-
System.IO.Error.
ioeGetHandle
:: IOError -> Maybe GHC.IO.Handle.Types.Handle#
-
System.IO.Error.
ioeGetLocation
:: IOError -> String# 根据传入的异常获取异常的属性。
-
System.IO.Error.
ioeSetErrorString
:: IOError -> String#
-
System.IO.Error.
ioeSetErrorType
:: IOError -> IOErrorType#
-
System.IO.Error.
ioeSetFileName
:: IOError -> Maybe FilePath#
-
System.IO.Error.
ioeSetHandle
:: IOError -> Maybe GHC.IO.Handle.Types.Handle#
-
System.IO.Error.
ioeSetLocation
:: IOError -> String# 根据传入的异常设置异常的属性。
1import System.Environment 2import System.IO 3import System.IO.Error 4 5main = toTry `catchIOError` handler 6 7-- | 程序的核心。 8-- 计算文件有多少行。 9toTry :: IO () 10toTry = do (fileName : _) <- getArgs 11 contents <- readFile fileName 12 let lnum = show . length . lines $ contents 13 putStrLn $ "The file has " ++ lnum ++ " lines!" 14 15-- | 处理 'IOError'。 16-- 若有已知异常,则发出警告,否则抛出。 17handler :: IOError -> IO () 18handler e 19 | isDoesNotExistError e = case ioeGetFileName e of 20 Just path -> 21 let w = show path ++ " " ++ ioeGetErrorString e ++ "." 22 in putStrLn w 23 Nothing -> putStrLn "No such file." 24 | otherwise = ioError e