<div class="gmail_quote">On Fri, Aug 21, 2009 at 5:03 AM, 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 6:57 PM, Peter Verswyvelen&lt;<a href="mailto:bugfact@gmail.com">bugfact@gmail.com</a>&gt; wrote:<br>
&gt;<br>
&gt; On Thu, Aug 20, 2009 at 11:23 PM, David Menendez &lt;<a href="mailto:dave@zednenem.com">dave@zednenem.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt; The important things to note are (1) getChar# depends on the token<br>
&gt;&gt; returned by putChar#, thus guaranteeing that putChar# gets executed<br>
&gt;&gt; first, and (2) putChar# and getChar# are impure and cannot normally be<br>
&gt;&gt; defined in Haskell.<br>
&gt;<br>
&gt; Ok, that I understand. But if getChar# and putChar# would be pure functions<br>
&gt; that just generate some output string / consume some input string, then this<br>
&gt; realworld token passing would not work when used with interact, since<br>
&gt; neither the output or input string really depends on the dummy token, unless<br>
&gt; using a seq again (or strictness annotation, which was explained to be just<br>
&gt; syntactic sugar for seq)?<br>
<br>
</div>I&#39;m not sure I understand your question, but I think it&#39;s possible to<br>
use interact in the way you want. For example, this code behaves<br>
correctly for me:<br>
<br>
    foo i =<br>
        let i1 = lines i<br>
        in &quot;Enter your name: &quot; ++<br>
            (case i1 of<br>
                [] -&gt; error &quot;EOF&quot;<br>
                name:i2 -&gt; &quot;Welcome &quot; ++ name ++ &quot;\n&quot;)<br>
<br>
Prelude&gt; interact foo<br>
Enter your name: Bob<br>
Welcome Bob</blockquote><div><br></div><div>Yes but this also enforce strictness, since you&#39;re pattern matching against the input, forcing it to be evaluated. If for example the empty string would be valid input, this wouldn&#39;t work, and seq would be needed again no?</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">Note the dependencies here. When you call interact foo, the prompt can<br>
be immediately output without reading any of the input. However,<br>
&quot;Welcome&quot; cannot be printed until one line of the input has been read<br>
(or EOF reached) because it&#39;s inside the pattern match on i1.<br>
<div class="im"><br>
<br>
&gt; But how would we then make a pure monad that can<br>
&gt; be used as in my example together with interact? I see no reason why to put<br>
&gt; everything in IO when it just comes to converting a stream of inputs to a<br>
&gt; stream of outputs? So interact really is useless, unless you just fmap<br>
&gt; something over the input or when the output is independent from the input?<br>
<br>
</div>Not necessarily. Your situation reminds me of Haskell&#39;s I/O system<br>
before the IO monad was introduced. (See section 7 of &quot;A History of<br>
Haskell: Being Lazy With Class&quot; for details.<br>
&lt;<a href="http://research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/history.pdf" target="_blank">http://research.microsoft.com/en-us/um/people/simonpj/papers/history-of-haskell/history.pdf</a>&gt;)<br>

<br>
In it, they describe how older versions of Haskell could be defined in<br>
terms of lazy request and response streams, how you can use<br>
continuation-passing to build the streams in a more localized way, and<br>
then how you could define the IO monad in terms of that.<br>
<br>
This works for me:<br>
<br>
import Control.Monad.Cont<br>
<br>
type Behavior = [String] -&gt; String<br>
type MyIO = Cont Behavior<br>
<br>
putLine :: String -&gt; MyIO ()<br>
putLine s = Cont $ \k ss -&gt; s ++ k () ss<br>
<br>
getLine :: MyIO String<br>
getLine = Cont $ \k (s:ss) -&gt; k s ss<br>
<br>
run :: MyIO () -&gt; Behavior<br>
run m = runCont m (\_ _ -&gt; [])<br>
<br>
foo = do<br>
    putLine &quot;Enter name: &quot;<br>
    name &lt;- getLine<br>
    putLine (&quot;Welcome &quot; ++ name ++ &quot;\n&quot;)<br>
<br>
Prelude Control.Monad.Cont&gt; interact (run foo . lines)<br>
Enter name: Dave<br>
Welcome Dave<br>
<br>
It may be instructive to manually expand &quot;run foo&quot;.</blockquote><div><br></div><div>This suffers from the same strictness problem on the input, e.g. when making getLine less strict, as in: </div><div><br></div>
<div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">import Prelude hiding (getLine)</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">import Control.Monad.Cont</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;"><br></span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">type Behavior = [String] -&gt; String</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">type MyIO = Cont Behavior</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;"><br>
</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">putLine :: String -&gt; MyIO ()</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">putLine s = Cont $ \k ss -&gt; s ++ k () ss</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;"><br></span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">getLine :: MyIO String</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;" size="4"><span class="Apple-style-span" style="font-size: 16px;">-- Was: getLine = Cont $ \k <b>(s:ss) -&gt; k s ss</b></span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large; "><b><font class="Apple-style-span" color="#009900">getLine = Cont $ \k ss -&gt; k (head ss) (tail ss)</font></b></span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;"><br></span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">run :: MyIO () -&gt; Behavior</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">run m = runCont m (\_ _ -&gt; [])</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;"><br>
</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">foo = do</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">   putLine &quot;Enter name: &quot;</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">   name &lt;- getLine</span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">   putLine (&quot;Welcome &quot; ++ name ++ &quot;\n&quot;)</span></font></div>
<div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;"><br></span></font></div><div><font class="Apple-style-span" face="&#39;courier new&#39;, monospace"><span class="Apple-style-span" style="font-size: large;">main = interact (run foo . lines)</span></font></div>
<div><br></div><div>You get the &quot;Welcome&quot; before the name again.</div><div><br></div><div>To be honest I don&#39;t fully understand why this is a horrible hack. From a pure point of view, the behavior is the same, weither or not the input is made strict. When side effects are present (interactive input/output from the user), it does matter, but aren&#39;t all space/time leaks to be considered as some sort of &quot;operational effects&quot;? In a pure mathematical world, space and time leaks would not really matter?</div>
<div><br></div><div>I do understand much more now, thanks. The best solution for making this IO pure remains MonadPrompt I guess.</div><div><br></div><div>Too bad that something extremely simple like console text IO doesn&#39;t seem to be a good start for introducing FRP, or maybe seen from another angle (using Reactive) it might still be, dono</div>
<div><br></div></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
<font color="#888888"><br>
--<br>
</font><div><div></div><div class="h5">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>
</div></div></blockquote></div><br>