What mechanism does Haskell use to actually decide to invoke the 4 actions below?
main :: IO ()
main = getLine >>= putStrLn >> getLine >>= putStrLn
Initially I thought it was to do with lazy evaluation, but... as from Real Word Haskell, about IO actions, they
produce an effect when performed, but not when evaluated
So I suspect it's some other mechanism rather than the system wanting to "evaluate" main. What is this mechanism? Or if it is evaluation, what is Haskell "wanting" to evaluate that causes it to execute the chain of actions?
As a first order approximation, the only source of evaluation in a Haskell program is main. What that means is that:
IO actions can be assembled and composed through >>=, >>, <*>, fmap, etc to produce any other IO actions butmain IO action will ever produce effects.In a sense all a Haskell program ever does is run main :: IO (). For anything to be evaluated, it has to stand in the way of running the IO action (this is where laziness fits). That begs the question: what does it mean to actually run an IO action?
Under the hood, IO ends up behaving like a (strict) State monad that threads through it a RealWorld state (which contains no information - it is symbolic of the state that side-effects encompass on the world), so "running" IO (sort of equivalent to State RealWorld) is like calling runState. Naturally, this runState can occur only once for any program - and this is exactly what main does (and what makes it magical)!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With