import IO
Section 7.3
第 7.3 节
To experiment with I/O errors, we need to get a bit creative. Generating an error is generally OS specific so instead we will use errors that are directly under user control. The function
要试验 I/O 错误,我们需要一点创造力。产生错误通常依赖于具体操作系统,
所以我们将改由用户直接掌控来制造错误。函数
userError :: String -> IOError
generates an error value and the function
生成一个错误值;而函数
ioeGetErrorString :: IOError -> String
gets the string out of an error.
从错误中取出字符串。
This version of getChar that raises an error when an @ or ? is entered:
下面是 getChar 的一个版本,当输入 @ 或 ? 时抛出错误:
getCharE :: IO Char
getCharE = do c <- getChar
case c of
'@' -> ioError (userError "@")
'?' -> ioError (userError "?")
_ -> return c
Using this extended getChar we can build getChar' to catch only @ There is currently a bug in Hugs - if this gets fixed change the definition is isAtError.
利用这个扩展的 getChar,我们可以构造只捕获 @ 的 getChar'。
Hugs 目前有个 bug——如果它被修复了,请更改 isAtError 的定义。
isAtError :: IOError -> Bool
isAtError e = ioeGetErrorString e == "User error: @" -- for bug in hugs
-- isAtError e = ioeGetErrorString e == "@" -- Should be this
getChar' :: IO Char
getChar' = getCharE `catch` atHandler where
atHandler e = if isAtError e then return '\n' else ioError e
getLine' :: IO String
getLine' = catch getLine'' (\err -> return ("Error: " ++ show err))
where
getLine'' = do c <- getChar'
if c == '\n' then return ""
else do l <- getLine'
return (c:l)
Observe the behavior when you enter @ or ?
观察你输入 @ 或 ? 时的行为。
e1 = getCharE
Now try lines with @ and ? in them.
现在试试包含 @ 和 ? 的行。
e2 = do l <- getLine'
putStrLn l
Section 7.4
第 7.4 节
You will have to set up some files to play with if you want to try this one.
如果想试这个例子,你得先准备一些文件来操作。
e3 = do fromHandle <- getAndOpenFile "Copy from: " ReadMode
toHandle <- getAndOpenFile "Copy to: " WriteMode
contents <- hGetContents fromHandle
hPutStr toHandle contents
hClose toHandle
putStr "Done."
getAndOpenFile :: String -> IOMode -> IO Handle
getAndOpenFile prompt mode =
do putStr prompt
name <- getLine
catch (openFile name mode)
(\_ -> do putStrLn ("Cannot open "++ name ++ "\n")
getAndOpenFile prompt mode)