7 Dec
Output
putStr :: String -> IO ()
prints the given string to stdout:
> putStr "Hello, World!\n"
Hello, World!
It takes a String
and does an IO
action which produces no result, indicated by the empty parentheses ()
.
Multiple actions can be chained together using the >>
operator:
> putStr "Hello" >> putChar ',' >> putStrLn " World!"
Hello, World!
Input
getLine :: IO String
consumes one line from from stdin:
> getLine
abc -- input followed by <enter>
"abc" -- the result from calling getLine
If the input string would be "abc\nxy"
, after calling getLine
, "xy"
would be left
Multiple actions can be combined using the bind operator >>=
:
> getLine >>= \str -> putChar (head str)
abc -- input followed by <enter>
a -- just the first letter
Input-Output
A function which yells everything you enter
loudEcho :: IO ()
loudEcho = getLine >>= \line ->
if line == "." then -- stop the loop on period
return () -- because loudEcho always returns an IO ()
else
putStr (map toUpper line) >> -- "yell" the input
putStrLn "!" >>
loudEcho -- keep looping
return :: a -> IO a
does nothing, but produces a value. For the input string "abc"
, calling return "!"
would produce "!"
and leave the input unchanged ("abc"
).
> loudEcho
hello -- input followed by <enter>
HELLO!!
world -- input followed by <enter>
WORLD!!
. -- break the loop
>
Do notation
Sequencing IO actions can also be done using the do
notation.
greet :: IO ()
greets the user:
greet = do
putStr "Please enter your name: "
getLine
putStrLn "Hello, there!"
It asks for your name but shows the same greeting regardless of input:
> greet
Please enter your name: Stefan -- input followed by <enter>
Hello, there!
personalGreet :: IO ()
offers a more personal touch:
personalGreet :: IO ()
personalGreet = do
putStr "Please enter your name: "
name <- getLine
let nameExcl = name ++ "!" -- no need for "in" in do notation
putStrLn ("Hello, " ++ nameExcl)
It doesn’t ignore the input given:
> personalGreet
Please enter your name: Stefan
Hello, Stefan!
Relation to bind >>=
var <- expr ...
becomesexpr >>= \var -> ...
e ...
becomese >> ...
For example,
do {
var1 <- expr1;
var2 <- expr2;
expr3;
expr4;
}
becomes:
expr1 >>= \var1 ->
expr2 >>= \var2 ->
expr3 >>
expr4
Brackets { }
create a separating block. Semicolons ;
separate multiple actions are written on the same row.
loudEcho
rewritten in do notation:
loudEcho' :: IO ()
loudEcho' = do
line <- getLine
if line == "." then -- stop the loop on period
return ()
else do
putStr (map toUpper line) -- "yell" the input
putStrLn "!!"
loudEcho' -- keep looping