Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between evaluating and performing IO actions: what causes Haskell to perform IO?

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?

like image 452
Michal Charemza Avatar asked Mar 07 '17 20:03

Michal Charemza


1 Answers

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 but
  • only the main 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)!

like image 85
Alec Avatar answered Sep 17 '22 17:09

Alec