Haskell 8

advertisement
Haskell
Chapter 8
Input and Output



What are I/O actions?
How do I/O actions enable us to do I/O?
When are I/O actions actually performed?
Review of Functional Language
characteristics





Haskell is purely functional
Provide definitions of what things are, Haskell figures out
the steps to execute
Functions are not allowed to have side effects
If a function is called two times with the same
parameters, it must return the same result (referential
transparency)
Helps us reason about our programs (e.g., don’t have to
trace entire program to see if some other function is
messing with your variables!)
I/O

But what about showing the result? That changes the
state of the screen… a side effect!

What to do???

Separate the “impure” parts of the program from the
“pure” parts.
Like FP on steroids
Our first program
main = putStrLn "Hello World!"
At the command prompt
 ghc --make helloworld
 helloworld (windows) or ./helloworld (nix)
What’s putStrLn?




Prelude> :t putStrLn
putStrLn :: String -> IO ()
putStr take a String, returns an IO action
An IO action…


does some action with a side effect (e.g., read input or write
output)
also yields a result
How does this work in GHCi?



*Main> putStrLn "howdy pardner"
howdy pardner
In GHCi, it performs the IO action and then prints it to
the terminal using putStrLn
What is getLine?


getLine is an IO action that yields a String
getLine is impure


*Main> :t getLine
getLine :: IO String
When are I/O actions performed?



Must give it a name (e.g., main) and then run the program
Can glue several I/O actions into one.
Don’t usually specify a type declaration for main – it has
signature of main :: IO something where something is a
concrete type, for example:


*Main> :t main
main :: IO ()
So what exactly is an IO action??






You can think of it as a box with feet.
Goes out into the world and does something
Maybe brings something back
Use <- to “open” the box and get the value
We can only take it out when we’re inside another IO
action
This won’t work!!

nameTag = "Hello, my name is " ++ getLine
How do the pure and impure parts interact?
main2 = do
putStrLn "Hello, what's your name?"
name <- getLine
putStrLn $ "Zis is your future: " ++ tellFortune name
tellFortune name
| name == "Lucky" = name ++ ",you will win a million dollars"
| otherwise = name ++ ", you will have no money but be happy"







*Main> main2
Hello, what's your name?
Lucky
Zis is your future: Lucky,you will win a million dollars
tellFortune is just a regular function!
*Main> tellFortune "Cyndi"
"Cyndi, you will have no money but be happy"
Bindings
import Data.Char
main3 = do
putStrLn "What's your first name? "
firstName <- getLine
putStrLn "What's your last name? "
lastName <- getLine
let bigFirstName = map toUpper firstName
let bigLastName = map toUpper lastName
putStrLn $ "hey " ++ bigFirstName ++ " "
++ bigLastName
++ ", how are you?“
 <- binds values from IO actions to names
 let binds pure expressions to names
More details - return

return() is not like other languages. 

return makes an I/O action out of a pure value (i.e., takes a value and “wraps” it
in an IO action box). Return does not end execution.
main4 = do
line <- getLine
if null line
remember: if must always have else
then return ()
else do
putStrLn $ reverseWords line
main4
reverseWords :: String -> String
reverseWords = unwords . map reverse . words
Understanding return
main5 = do
return ()
return "HAHAHA"
line <- getLine
return "BLAH BLAH"
return 4
putStrLn line

Creates lots of I/O actions that are not used
More on return
main6 = do
a <- return "Hello"
b <- return "World"
putStrLn $ a ++ " " ++ b



Quick trace: what is this doing?
More likely to use let in this scenario… but it illustrates
how return works
Common to use return when last statement of do
doesn’t have desired result. So create a return that yields
the desired result, put it at the end
Also used when we need an IO action that doesn’t do
anything (like the return () in main4)
Other useful functions



putStr – like putStrLn, but no newline
putChar – takes a character and returns an IO action that
will print it to the terminal - putChar 'a'
print – takes a value that’s an instance of Show (i.e., we
know how to represent as string), applies show to
stringify it, outputs string to terminal - print "haha"
when
when – syntactic sugar. Takes Bool & I/O, returns I/O
 when :: Monad m => Bool -> m () -> m ()
import Control.Monad
main7 = do
input <- getLine
if (input == "SWORDFISH")
then putStrLn input
else return ()

main8 = do
input <- getLine
when (input == "SWORDFISH") $ do
putStrLn input
sequence
sequence takes a list of I/O actions, returns an I/O action
that performs those actions one after the other
main9 = do
a <- getLine
b <- getLine
c <- getLine
print [a,b,c]

main10 = do
rs <- sequence [getLine, getLine, getLine]
print rs
mapM










Common scenario: map a function that returns an I/O action
(e.g., print) over a list and then sequence it. mapM does this
for us, mapM_ does it but throws away the result.
*Main> mapM print [1,2,3]
1
2
3
[(),(),()]
*Main> mapM_ print [1,2,3]
1
2
3
Other useful functions in book


forever
forM
Play and Share?

Let’s start on the homework
Download