@popefucker@cybre.space for functions with no side effects (those that just take something and return something) it doesn't matter what order we do them in.
but functions that ask the user questions and wait for responses? the order matters!
so we have to wrap up whatever our function does in a higher order type:
askAndResponse :: String -> IO (String)
let's say this function displays whatever string we pass to it to the user, then waits for user response...
@popefucker@cybre.space ...but now we can't compose it!
if we have:
reverse :: String -> String
we can't write
reverse (askAndResponse "what's your name?")
because askAndResponse doesn't return a String. It returns an IO String, which is something else
without monads, we'd be stuck - we can't use our results easily.
But if we make sure IO follows the monad laws, we can use the function >>= to compose:
askAndResponse "name?" >>= reverse
which makes writing code w/ effects easier