<div class="gmail_quote">On Thu, Apr 9, 2009 at 8:47 PM, Brandon S. Allbery KF8NH <span dir="ltr">&lt;<a href="mailto:allbery@ece.cmu.edu">allbery@ece.cmu.edu</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">Yes.  That&#39;s the opaque &quot;real world&quot;;  an I/O operation conceptually modifies this state, which is how things get tied together.  Ordinary user programs can&#39;t interact with the &quot;real world&quot; sate except via functions defined on IO, which are assumed to modify the state; that&#39;s exactly how non-RT actions are modeled via RT code.<br>
</div>
<br>
Stuff like forkIO and newIORef can also be understood that way, it&#39;s just a bit more complex to follow them around.</blockquote><div><br></div><div>newIORef is trivial: just keep a unique counter in the state.</div><div>
<br></div><div>Have you tried forkIO?  I used to think that &quot;world passing&quot; was an acceptable, if ugly, semantics for IO.  However, after doing some formal modeling, I realized that forkIO breaks the model altogether.  What happens to the end state of the forked thread? </div>
<div><br></div><div>If it really is thought of that way, surely you will be able to create a pure IO simulator as a state monad (for an arbitrarily complex world) that handles only forkIO, threadDelay, and print  (just using a write buffer).  Think about that for a second.</div>
<div><br></div><div>Luke</div><div><br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
<br>
Please note that ghc *does* implement IO (from Core up, at least) this way, modulo unboxed tuples, so claims that it is &quot;wrong&quot; are dubious at best.<div class="im"><br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    s &lt;- readFile &quot;/my_file&quot;<br>
    writeFile &quot;/my_file&quot; &quot;Hello, world!\n&quot;<br>
    threadDelay 10000 -- If you don&#39;t like threadDelay, just substitute forcing<br>
                      -- an expensive thunk here<br>
    writeFile &quot;/my_file&quot; s<br>
<br>
As a function from initial state to final state, this program is just<br>
the identity; but surely this program should be considered different<br>
</blockquote>
<br></div>
It is?<br>
<br>
&gt; -- these implicitly are considered to return a modified RealWorld<br>
&gt; readFile :: RealWorld -&gt; (String,RealWorld)<br>
&gt; writeFile :: RealWorld -&gt; ((),RealWorld)<br>
&gt; threadDelay :: RealWorld -&gt; ((),RealWorld)<br>
&gt;<br>
&gt; main :: RealWorld -&gt; ((),RealWorld)<br>
&gt; main state =<br>
&gt;   case readFile state &quot;/my_file&quot; of<br>
&gt;     (s,state&#39;) -&gt;<br>
&gt;        case writeFile state&#39; &quot;/my_file&quot; &quot;Hello, world!\n&quot; of<br>
&gt;          (_,state&#39;&#39;) -&gt;<br>
&gt;             case threadDelay state&#39;&#39; 10000 of<br>
&gt;               (_,state&#39;&#39;) -&gt; writeFile &quot;/my_file&quot; s   <br>
<br>
This is just the State monad, unwrapped.  And the differences between this and the actual GHC implementation are the use of unboxed tuples and RealWorld actually being a type that can&#39;t be accessed by normal Haskell code.<br>
<font color="#888888">
<br>
-- <br></font><div><div></div><div class="h5">
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] <a href="mailto:allbery@kf8nh.com" target="_blank">allbery@kf8nh.com</a><br>
system administrator [openafs,heimdal,too many hats] <a href="mailto:allbery@ece.cmu.edu" target="_blank">allbery@ece.cmu.edu</a><br>
electrical and computer engineering, carnegie mellon university    KF8NH<br>
<br>
<br>
</div></div></blockquote></div><br>