On Sun, Mar 1, 2009 at 11:59 AM, Will Ness <span dir="ltr">&lt;<a href="mailto:will_n48@yahoo.com">will_n48@yahoo.com</a>&gt;</span> wrote:<br><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
The IO-action is not the I/O operation in the real world, but an action of<br>
recording a promise to perform it.<br>
<br>
Any IO primitive can be seen as latching this hidden promise onto its explicit<br>
return value, thus creating a monadic value (:: IO a), carrying along this<br>
hidden promise. IO bind combines these promises into a combined record, or log,<br>
of promises to perform actual I/O activity, if called upon by the system.<br>
<br>
That recording of a promise is the IO-action that IO monad is about, from pure<br>
Haskell standpoint.<br>
</blockquote><div><br>Ok, I kinda like the idea of accumulating a &quot;log&quot; of promised actions, although I&#39;d suggest a different term since log usually means history.  Maybe antilog or prelog or future trace or the like.  In any case, I think that&#39;s useful for explaining lazy evaluation, but it&#39;s not directly implicated by monad semantics.  IOW monad semantics and evaluation strategy are (mostly) orthogonal. <br>
</div><div> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
Another monad will have another meaning for its actions, latching another<br>
hidden data on their results, but they still can be seen as actions, in context<br>
of being sequenced and combined by that monad&#39;s bind.<br>
</blockquote><div><br>I see, you&#39;re thinking of action as something like the promised eval.  As opposed to the action of performing actual IO.  I fear that might confuse newcomers, though; probably better to stick with &quot;function&quot; terminology and discuss evaluation separately. <br>
</div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br><div class="Ih2E3d">
&gt; Correction:  special name for IO &quot;functions&quot; (actually &quot;IO terms&quot; would be<br>
better). <br>
<br>
<br>
</div>Why? They are just fuctions, of type (Monad m =&gt; a -&gt; m b). What I&#39;m saying,<br>
they are of special type, chainable by the M monad, so it seems logical to have<br>
a special name for such M-chainable functions, e.g. &quot;M-action functions&quot;<br>
(whatever the M).<br>
</blockquote><div><br>Technically they cannot be functions - there&#39;s no &quot;same input, same output&quot; (at least not for input operations).  No referential transparency.  That&#39;s the problem.<br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
&gt;<br><div class="Ih2E3d">
&gt; This was a big problem for me; I find terms<br>
like &quot;action&quot;, &quot;computation&quot;, &quot;function&quot; completely misleading for IO<br>
terms/values. <br>
<br>
<br>
</div>Why? A function of type (a -&gt; M b) is a function that returns a value, (:: M<br>
b), tagged with some monadic hidden data. In case of IO, it is a promise to <br></blockquote><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
perform some actual I/O that&#39;s passed around, hidden. But the M-action function<br>
itself is just a regular Haskell function. It can be defined elsewhere,<br>
anywhere.<br>
</blockquote><div><br>But the &quot;promise to perform&quot; is a matter of evaluation semantics, not denotational semantics.  Denotationally these things cannot be functions.<br><br>I saw your other note too.  I think the idea that the runtime builds a &quot;future log&quot; is useful - simple and pretty easy to grok.  But I would recommend keeping a clear distinction between Haskell&#39;s language semantics (denotational) and its compiler/runtime semantics (evaluational).  Denotationally, all a monad does is ensure sequencing, which is necessary to properly order the (non-deterministic) IO values.  With lazy eval this gets translated into the building of a &quot;future log&quot; etc.<br>
<br>Thanks,<br><br>-gregg<br></div></div>