Download IO Auction and more Study notes Computer Science in PDF only on Docsity!
CS 457/557 Functional Programming
Lecture 3
IO Actions; Graphics
Can we be imperative?
- All the programs we have seen so far have no “sideeffects.” That is, programs are executed only for their values.
- But sometimes we want our programs to affect the real world (reading, printing, drawing a picture, controlling a robot, etc).
- (^) Yet, IO operations (and other “effectful” operations) don't mix well with Haskell's lazy evaluation, because evaluation order is very complicated and hard to predict. - How can we reconcile purity and utility?
IO Actions
- In Haskell, “pure values” are separated from “worldly actions”, in two ways: - Types : An expression with type IO a has possible actions associated with its execution, while returning a value of type a. - Syntax : The do syntax performs an action, and (using layout) allows one to sequence several actions.
- (^) Example: code to read a character, echo it, and return Boolean value indicating if it was a newline do c <- getChar putChar c return (c == '\n')
Some Predefined IO Actions
-- get one character from keyboard getChar :: IO Char -- write one character to terminal putChar :: Char -> IO() -- get a whole line from keyboard getLine :: IO String -- read a file as a String readFile :: FilePath -> IO String -- write a String to a file writeFile :: FilePath -> String -> IO ()
do Typing Details
:: IO Bool (the type of the last action also determines the type of the entire do expression) :: Char do c <- getChar putChar c return (c == '\n') :: IO Char
:: IO ()
(actions without “v <- …” usually have this type)
When are IO Actions Performed?
- A value of type IO a is an action, but it is still a value: it
will only have an effect when it is performed.
- (^) In Haskell, a program’s value is the value of the variable
main in the module Main. That value must have type IO
a. The associated action will be performed when the
whole program is run.
- In Hugs, however, you can type any expression to the
Hugs prompt. If the expression has type IO a it will be
performed; otherwise its value will be printed on the
display.
- There is^ no^ other way to perform an action (well, almost).
Actions are just values
- Actions are just like other (firstclass) values: they can
be passed, returned, stored, etc.
- For example, it can be handy to build lists of actions, e.g. putCharList :: String -> [IO ()] putCharList cs = [putChar c | c <- cs]
- There's a library function to convert this to a single
action
sequence_ :: [IO a] -> IO () putStr :: String -> IO () putStr s = sequence_ (putCharList s)
- (^) Remember, actions are only executed at top level, e.g. main = putStr “abc”
Example: Unix wc Command
- (^) The unix wc (word count) program reads a file and
then prints out counts of characters, words, and
lines.
- (^) Reading the file is an action, but computing the
information is a pure computation.
- Strategy:
- Define a pure function that counts the number of
characters, words, and lines in a string.
» number of lines = number of ‘\n’
» number of words ~= number of ‘ ’ plus
number of ‘\t’
- Define an action that reads a file into a string,
applies the above function, and then prints out
the result.
Example Run
Main> wc
elegantProse.txt
The file: elegantProse.txt has
2970 characters
1249 words
141 lines
Main>
I typed this.
Graphics Actions
- Graphics windows are traditionally programmed
using commands; i.e. actions.
- Some graphics actions relate to opening up a graphics
window, closing it, etc.
- Others are associated with drawing lines, circles, text,
etc.
Graphics Operators
- openWindow :: String -> Point -> IO Window
- (^) Opens a titled window of a particular size.
- drawInWindow :: Window -> Graphic -> IO ()
- Displays a Draw () value in a given window.
- (^) Note that the return type is IO ().
- getKey :: Window -> IO Char
- Waits until a key is pressed and then returns the character associated with the key.
- closeWindow :: Window -> IO ()
- runGraphics :: IO () -> IO ()
- Required “wrapper” around graphics operations to init/close graphics system.
Mixing Graphics IO
with Terminal IO
spaceClose :: Window -> IO () spaceClose w = do k <- getKey w if k == ' ' then closeWindow w else spaceClose w main1 = runGraphics ( do w <- openWindow "Second Program" (300,300) drawInWindow w (text (100,200) “Hello Again") spaceClose w )
Coordinate System
Increasing x-axis Increasing y-axis
Example Program
main2 = runGraphics ( do w <- openWindow "Draw some shapes" (300,300) drawInWindow w (ellipse (0,0) (50,50)) drawInWindow w (shearEllipse (0,60) (100,120) (150,200)) drawInWindow w (withColor Red (line (200,200) (299,275))) drawInWindow w (polygon [(100,100),(150,100),(160,200)]) drawInWindow w (withColor Green (polyline [(100,200),(150,200), (160,299),(100,200)])) spaceClose w )