File: part15.lhs

package info (click to toggle)
haskell98-tutorial 200006-3
  • links: PTS
  • area: main
  • in suites: sarge
  • size: 624 kB
  • ctags: 11
  • sloc: haskell: 2,125; makefile: 80; sh: 13
file content (97 lines) | stat: -rw-r--r-- 2,531 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
Gentle Introduction to Haskell 98, Online Supplement 
Part 15
Covers Section 7.3, 7.3, 7.5 

> module Part15() where

> import IO

Section 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

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:

> 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.

> 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

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)
>

Continued in part16.lhs