<div>But how does GHC implement the RealWorld internally? I guess this can&#39;t be done using standard Haskell stuff? It feels to me that if I would implement it, I would need seq again, or a strict field, or some incrementing &quot;time&quot; value that is a strict argument of each of the IO primitives. In any case, I would need strictness to control the dependencies no? I might be wrong (again) but this is all very interesting ;-)</div>
<div><div><div><div><br><div><br><div class="gmail_quote">On Thu, Aug 20, 2009 at 10:25 PM, David Menendez <span dir="ltr">&lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">On Thu, Aug 20, 2009 at 3:43 PM, Peter Verswyvelen&lt;<a href="mailto:bugfact@gmail.com">bugfact@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; Also doesn&#39;t Haskell&#39;s IO system uses a hidden RealWorld type that has no<br>
&gt; value but which is passed from between monadics binds in a strict way to<br>
&gt; make the ordering work?<br>
<br>
</div>Haskell only describes how the IO monad behaves. GHC&#39;s implementation<br>
uses a RealWorld type, but other implementations are possible.<br>
<br>
A quick sketch of an alternative implementation,<br>
<br>
data Trace = Done | Get (Char -&gt; Trace) | Put Char Trace<br>
<br>
newtype IO a = IO { unIO :: (a -&gt; Trace) -&gt; Trace }<br>
<br>
instance Monad IO where<br>
    return a = IO (\k -&gt; k a)<br>
    m &gt;&gt;= f = IO (\k -&gt; unIO m (\a -&gt; unIO (f a) k))<br>
<br>
getChar :: IO Char<br>
getChar = IO Get<br>
<br>
putChar :: Char -&gt; IO ()<br>
putChar c = IO (\k -&gt; Put c (k ()))<br>
<br>
The run-time system is responsible for interpreting the Trace and<br>
inputting/outputting characters as needed. All of IO can be<br>
implemented in this manner.<br>
<div class="im"><br>
&gt; So IO in Haskell is a horrible hack then? :-) If it<br>
&gt; would be done nicely, in the FRP way, then RealWorld IO would need time<br>
&gt; stamps to get rid of the hack?<br>
<br>
</div>Again, no. GHC&#39;s IO type uses the RealWorld value to create data<br>
dependencies. For example, putChar &#39;x&#39; &gt;&gt; getChar, the getChar depends<br>
on the RealWorld returned by putChar &#39;x&#39;.<br>
<br>
This is why it&#39;s dangerous to open up GHC&#39;s IO type unless you know<br>
what you&#39;re doing. If you aren&#39;t careful, you may accidentally<br>
duplicate or destroy the RealWorld, at which point you risk losing<br>
purity and referential transparency.<br>
<br>
I suppose you could consider the fact that GHC&#39;s IO is implemented<br>
using impure primitive operations a hack, but the whole point of the<br>
IO monad is to hide that impurity from the rest of the program.<br>
<font color="#888888"><br>
--<br>
Dave Menendez &lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt;<br>
&lt;<a href="http://www.eyrie.org/~zednenem/" target="_blank">http://www.eyrie.org/~zednenem/</a>&gt;<br>
</font></blockquote></div><br></div></div></div></div></div>