>> All Haskell programs start as
>>> main :: IO ()
>>> though... so they all get evaluated in the context of another IO ()
>> don't they?
True for most cases now, but historically false. Haskell existed and people
wrote programs for years before the Monad class and IO were created. A
Haskell98 program can be taken to have a "main :: IO ()", but that is not essential.
Which is the point jcc made:
>> Well... Haskell compilers and runhaskell-style interpreters (not
> regular Hugs/ghci!) take the value of Main.main as `the program'. But
> that feels (to me --- I could be wrong) like an aspect of a particular
> hosted environment. REPLs can handle programs that aren't wrapped up in
> IO at all; and there's no reason why IO has to be the type of
> IO-performning-things in REPLs, either. You could just as well write a
> REPL that took, say, tangible values [http://haskell.org/haskellwiki/TV]> as input instead, and displayed them. So it's more a matter of Haskell
> implementations can be given an IO value to run than that combining IO
> values together somehow runs them.
>> jcc