CSCE 314 Lecture 17

From Notes
Jump to navigation Jump to search

« previous | Wednesday, October 5, 2011 | next »


Interactive Programs

Haskell functions are "pure": When we call a function with the same arguments, that function will always return the same value (the mathematical sense of a function)

This means that the following functions cannot be defined:

-- return a random integer
rand :: () -> Int

-- read a character from stdin
getCharacter :: () -> Char

-- put a character to stdout
putCharacter :: Char -> ()

The last one might look okay, but the side effect (something that happens outside the scope of the code) is not guaranteed to happen because of laziness:

Laziness and side effects are a bad combination

The IO Type

type IO a = World -> (a, World)

Generally, IO takes the world as an input, and returns a new world in a different state. This physically cannot be done, and ignoring the state of the world would result in a "contaminated function"

A value of type IO a is called an "action" and does something before delivering a value of type a

3 Basic actions:

  1. getCharacter :: IO Char
  2. putCharacter :: Chan -> IO ()
  3. return :: a -> IO a (just like our Monad return function)

The third item brings up an interesting point: we can use the Bind operator on IO:

getLine IO String
getLine = getChar >>= \x ->
    if x == '\n' then return []
        else (getLine >>= \xs -> return (x:xs))

putStr :: String -> IO ()
putStr [] = return ()
putStr (x:xs) = putChar x >> putStr xs

putStrLn :: String -> IO ()
putStrLn xs = putStr xs >> putChar '\n'

Calling one of these IO functions does not execute the code. Instead it creates a huge monstrous function thing composed of a bunch of bound actions that waits until we "run the monad": the compiler/interpreter makes a huge monad thing then passes the world to it.