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