# Introduction To Haskell

Lecture 8

Input/Output

### Using These Slides

#### Every slide has a secret note.

• On Chrome: press `F12`, then click Console
• On IE: press `F12`, then click Console
• On Firefox: `Ctrl+Shift+k`

### Shortcut Keys:

 `↓`, `PgDn`, `n`, `j` next slide `↑`, `PgUp`, `p`, `k` prev slide `Esc` enables `ctrl+f` globally

### Review of Homework 7

Find the intersect of two lines using an existing package
 A B
``````
-- Designed by Anish S. Tondwalkar
import Graphics.Gloss.Data.Point
import Graphics.Gloss.Geometry.Line

-- A line is specified by two points (a point is a pair of Floats)
data Line = L Point Point

-- takes two lines instead of two points
intersectLines (L a b) (L c d) = intersectLineLine a b c d

``````

### Pure

Remember, Haskell is pure.

• Functions can't have side-effects
• Functions take in inputs and compute outputs
• Nothing else happens in-between

(no modification of global variables)

However, input/output is not at all pure. There is a side effect! By displaying output pixels on your monitor, you are changing the global state of your computer.

## Output

Let's print out some output!

Create a file `Main.hs` and write the following code

``````
module Main where

main = do
putStrLn "Hello world!"
putStrLn "main is a function"
putStrLn "of type IO ()"
``````

Run the code

 Use GHCi `````` \$ ghci Prelude> :load Main.hs *Main> main `````` Or just use `runhaskell` `````` \$ runhaskell Main.hs `````` Or compile the code! `````` \$ ghc --make Main.hs \$ ./Main ``````

### `main`

`main` is the "entry point of a Haskell program" *

It must be an IO type.

``````
\$ ghci Main.hs
*Main> :t main
main :: IO ()
``````

It's like the `main` from Java or C++. When you compile Haskell code, the `main` function runs.

### `do`

glues together multiple IO actions

`do` is a keyword in Haskell, like `let` or `where`.

``````
main = do
putStrLn "this line is the first IO action"
putStrLn "putStrLn has type String -> IO ()"
putStrLn "we are glueing together multiple IO ()"
``````

## Input

Input is just as straight forward.

The `getLine` function binds input to a variable.

``````
module Main where

main = do
putStrLn "Why did the banker leave his job?"
answer <- getLine
putStrLn (if answer == "he lost interest"
then "Correct!"
else "Wrong!")
``````

### `<-`

We have seen the `<-` symbol before

``````
[ x | x<-[1..10], even x ]
``````

The symbol is pronounced "drawn from"

``````
main = do
input <- getLine
putStrLn ("you wrote: " ++ input)
``````

"input is drawn from getLine"

## IO

If you see IO, think side effects.

`putStrLn` displays something to your monitor. That's a side effect!

putStrLn gives back nothing, ()

``````
Prelude> :t putStrLn
putStrLn :: String -> IO ()
``````

getLine gives back a String to use

``````
Prelude> :t getLine
getLine :: IO String
``````

### Pure

Side-effects are isolated into I/O actions.

Pure code is separated from impure operations.

I/O actions only exist within other I/O actions.

### Brilliant! ### `return`

`return` is a function that "makes an I/O action out of a pure value" *

``````
Prelude> :t return
return :: Monad m => a -> m a
``````

`return "hello" :: IO String`

It's pretty much the opposite of the `<-` syntax.

``````
main = do
input <- return "hello"
putStrLn input
``````

`return` packs up a value into an IO box. `<-` extracts the value out of an IO box.

### Using `return`

In this program, we exit when the input is "y"

``````
module Main where

main = do
putStrLn "quit the program? y/n"
ans <- getLine
if ans /= "y" then do
putStrLn "not quitting"
main
else return ()
``````

return () has the type IO ()

We create an IO that doesn't do anything so that the program could exit.

### `when`

The when function from Control.Monad module looks nicer

`when :: Monad m => Bool -> m () -> m ()`

 Old code New code `````` module Main where main = do putStrLn "quit? y/n" ans <- getLine if ans /= "y" then do putStrLn "not quitting" main else return () `````` `````` module Main where import Control.Monad main = do putStrLn "quit? y/n" ans <- getLine when (ans /= "y") \$ do putStrLn "not quitting" main ``````

### `sequence`

sequence evaluates each IO action from a list of actions and returns a list of IO outputs

`sequence :: Monad m => [m a] -> m [a]`

``````
Prelude> sequence [getLine, getLine]
hello
world
["hello","world"]
``````
``````
Prelude> sequence (map print [1,2])
1
2
[(),()]
``````

print is equivalent to putStrLn.show

### `mapM`

mapM takes care of the sequencing stuff

``````
Prelude> mapM print [1,2,3]
1
2
3
[(),(),()]
``````

and mapM_ is the same but doesn't output anything afterwards

``````
Prelude> mapM_ print [1,2,3]
1
2
3
``````

### `interact`

interact makes I/O really easy.

Just call `interact` on a String -> String function and you're done!

This code counts the number of characters per line
``````
module Main where

main = interact countChars

countChars :: String -> String
countChars str =
let allLines = lines str
lengths  = map (show.length) allLines
in unlines lengths
``````

## File Input

Let's count the number of lines in a file,
It's best to keep the pure code separate from the ugly IO stuff
``````
module Main where

import System.IO

main = do
theInput <- readFile "input.txt"
putStrLn (countLines theInput)

countLines :: String -> String
countLines str = (show (length (lines str)))
``````

## File Output

Writing to file is done with writeFile

``````
module Main where

import System.IO

main = do
putStrLn "writing to file..."
writeFile "output.txt" ['A'..'Z']
``````
writeFile will overwrite the file. Use appendFile if you'd like to append instead

# Homework

## Wrestling with Haskell

1. Fill out this form!
2. Research 5 facts about Monads
3. Write an IO program that reverses text

given a file containing some text, create an output file with everything in reverse

 input.txt output.txt `````` hello world `````` `````` dlrow olleh ``````