CSCE 314 Lecture 17
« 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:
- getCharacter :: IO Char
- putCharacter :: Chan -> IO ()
- 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.