Presentation is loading. Please wait.

Presentation is loading. Please wait.

Chapter 16 Communicating With the Outside World. Motivation  In Chapter 3 we learned how to do basic IO, but it was fairly limited.  In this chapter.

Similar presentations


Presentation on theme: "Chapter 16 Communicating With the Outside World. Motivation  In Chapter 3 we learned how to do basic IO, but it was fairly limited.  In this chapter."— Presentation transcript:

1 Chapter 16 Communicating With the Outside World

2 Motivation  In Chapter 3 we learned how to do basic IO, but it was fairly limited.  In this chapter we investigate advanced IO ideas: file handles, channels, exceptions, and concurrency.  The ideas developed here will be used in the next chapter to write a renderer for FAL.  The ideas will continue to be cast in terms of “IO actions” of type “IO a”, and will be sequenced using Haskell’s “do” syntax.  The “mysteries” underlying the type “IO” and Haskell’s “do” syntax will be revealed in Chapter 18. (Guess what’s underneath it all? Yes, functions! )

3 File Handles  Recall from Chapter 3 the IO actions: writeFile:: FilePath -> String -> IO () appendFile:: FilePath -> String -> IO () type FilePath = String  These functions open a file, write a string, and then close the file.  But if many successive writes are needed, the repeated openings and closings can be very inefficient.  Better to open a file, and leave it open until done: openFile:: FilePath -> IOMode -> IO Handle hClose:: Handle -> IO () data IOMode = ReadMode | WriteMode | AppendMode | ReadWriteMode

4 File Operations  Once open, many file operations are possible: hPutChar :: Handle -> Char -> IO () hPutStr :: Handle -> String -> IO () hPutStrLn :: Handle -> String -> IO () hPrint :: Show a => Handle -> a -> IO () hGetChar :: Handle -> IO Char hGetLine :: Handle -> IO String hGetContents :: Handle -> String when in “WriteMode” when in “ReadMode”

5 Standard Channels  As in many OS’s, certain kinds of IO are treated like files. In Haskell these are called channels, and include standard input (stdin), standard output (stdout), and standard error (stderr).  Indeed, these two functions are pre-defined in the Prelude: getChar :: IO Char getChar = hGetChar stdin putChar :: IO () putChar = hPutChar stdout

6 Exceptions  There are many ways that an IO action might fail, and we need a way to detect and recover from such failures.  In Haskell, IO failures are called exceptions, and they can be “caught” by: catch :: IO a -> (IOError -> IO a) -> IO a  For example: getChar' :: IO Char getChar' = catch getChar (\e -> return '\n')

7 Dispatching on IOError  IoError is an abstract type with predicates such as: isEOFError :: IOError -> Bool isDoesNotExistError :: IOError -> Bool and a “throw” operation: ioError :: IOError -> IO a  A “more refined” getChar can then be defined: getChar' :: IO Char getChar' = catch getChar (\e -> if isEOFError e then return '\n‘ else ioError e ) Note how ioError “throws” the error to an outer dynamic scope.  (See text for example of “nested” exceptions.)

8 Putting It All Together (copying a file) getAndOpenFile :: String -> IOMode -> IO Handle getAndOpenFile prompt mode = do putStr prompt name do putStrLn ("Cannot open " ++ name) print error getAndOpenFile prompt mode ) Main :: IO () main = do fromHandle <- getAndOpenFile "Copy from: " ReadMode toHandle <- getAndOpenFile "Copy to: " WriteMode contents <- hGetContents fromHandle hPutStr toHandle contents hClose fromHandle hClose toHandle putStrLn "Done."

9 First-Class Channels  “First-class channels” are different from the “standard channels” described earlier.  They are a mechanism through which Haskell “processes” can communicate asynchronously.  A first-class channel containing values of type “a” has type “Chan a”.  The key operations are: newChan:: IO (Chan a) writeChan:: Chan a -> a -> IO () readChan:: Chan a -> IO a getChanContents:: Chan a -> IO [a] isEmptyChan:: Chan a -> IO Bool

10 Example  A first-class channel implements an unbounded queue that can be written to and read from asynchronously.  For example: do c <- newChan writeChan c `a` writeChan c `b`... do... a <- readChan c b <- readChan c return [a,b] returns the string "ab".

11 Concurrency  Concurrent processes may be forked off from the main computation by forkIO :: IO () -> IO ()  The IO action: forkIO p will cause p to run concurrently with the main program.  For example, we can create a concurrent version of the client-server program from Chapter 14. [ see next slide ]

12 Concurrent Client-Server client :: Chan Int -> Chan Int -> IO () client cin cout = do writeChan cout 1 loop where loop = do c <- readChan cin print c writeChan cout c loop server :: Chan Int -> Chan Int -> IO () server cin cout = do loop where loop = do c <- readChan cin writeChan cout (c+1) loop main :: IO () main = do c1 <- newChan :: IO (Chan Int) c2 <- newChan :: IO (Chan Int) forkIO (client c1 c2) forkIO (server c2 c1)


Download ppt "Chapter 16 Communicating With the Outside World. Motivation  In Chapter 3 we learned how to do basic IO, but it was fairly limited.  In this chapter."

Similar presentations


Ads by Google