This thread pretty much exemplifies why many people don&#39;t bother with this mailing list anymore.<br><br><div class="gmail_quote">On Sun, Jan 1, 2012 at 7:00 PM, AUGER Cédric <span dir="ltr">&lt;<a href="mailto:sedrikov@gmail.com">sedrikov@gmail.com</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Le Sun, 1 Jan 2012 16:31:51 -0500,<br>
Dan Doel &lt;<a href="mailto:dan.doel@gmail.com">dan.doel@gmail.com</a>&gt; a écrit :<br>
<div class="im"><br>
&gt; On Sun, Jan 1, 2012 at 3:26 PM, Ketil Malde &lt;<a href="mailto:ketil@malde.org">ketil@malde.org</a>&gt; wrote:<br>
&gt; &gt; Chris Smith &lt;<a href="mailto:cdsmith@gmail.com">cdsmith@gmail.com</a>&gt; writes:<br>
&gt; &gt;<br>
&gt; &gt;&gt;&gt; I wonder: can writing to memory be called a “computational<br>
&gt; &gt;&gt;&gt; effect”? If yes, then every computation is impure.<br>
&gt; &gt;<br>
&gt; &gt; I wonder if not the important bit is that pure computations are<br>
&gt; &gt; unaffected by other computations (and not whether they can affect<br>
&gt; &gt; other computations). Many pure computations have side effects<br>
&gt; &gt; (increases temperature, modifies hardware registers and memory,<br>
&gt; &gt; etc), but their effect can only be observed in IO.<br>
&gt; &gt;<br>
&gt; &gt; (E.g. Debug.Trace.trace provides a non-IO interface by use of<br>
&gt; &gt; unsafePerformIO which is often considered cheating, but in<br>
&gt; &gt; this view it really is pure.)<br>
&gt;<br>
&gt; The point of purity (and related concepts) is to have useful tools for<br>
&gt; working with and reasoning about your code. Lambda calculi can be seen<br>
&gt; as the prototypical functional languages, and the standard ones have<br>
&gt; the following nice property:<br>
&gt;<br>
&gt;   The only difference between reduction strategies is termination.<br>
&gt;<br>
&gt; Non-strict strategies will terminate for more expressions than strict<br>
&gt; ones, but that is the only difference.<br>
<br>
</div>This has nothing to do with purity (purity and strictness/lazyness<br>
are different).<br>
<div class="im"><br>
&gt;<br>
&gt; This property is often taken to be the nub of what it means to be a<br>
&gt; pure functional language. If the language is an extension of the<br>
&gt; lambda calculus that preserves this property, then it is a pure<br>
&gt; functional language. Haskell with the &#39;unsafe&#39; stuff removed is such a<br>
&gt; language by this definition, and most GHC additions are too, depending<br>
&gt; on how you want to argue. It is even true with respect to the output<br>
&gt; of programs, but not when you&#39;re using Debug.Trace, because:<br>
&gt;<br>
&gt;     flip (+) (&quot;foo&quot; `trace` 1) (&quot;bar&quot; `trace` 1)<br>
&gt;<br>
&gt; will print different things with different evaluation orders.<br>
&gt;<br>
&gt; A similar property is referential transparency, which allows you to<br>
&gt; factor your program however you want without changing its denotation.<br>
&gt; So:<br>
&gt;<br>
&gt;     (\x -&gt; x + x) e<br>
&gt;<br>
&gt; is the same as:<br>
&gt;<br>
&gt;     e + e<br>
&gt;<br>
<br>
</div>That is not really what I call referential transparency; for me this is<br>
rather β reduction…<br>
<br>
For me, referential transparency means that the same two closed<br>
expression in one context denote the same value.<br>
<br>
So that is rather:<br>
<br>
let x = e<br>
    y = e<br>
in x + y<br>
<div class="im"><br>
is the same as:<br>
<br>
e + e<br>
<br>
&gt; This actually fails for strict evaluation strategies unless you relax<br>
&gt; it to be &#39;same denotation up to bottoms&#39; or some such. But not having<br>
&gt; to worry about whether you&#39;re changing the definedness of your<br>
&gt; programs by factoring/inlining is actually a useful property that<br>
&gt; strict languages lack.<br>
<br>
</div>In fact, strict language can be referentially transparent; it is the<br>
case in ML (in fact I only know of Ocaml minus impure features, but<br>
well…).<br>
<div class="im"><br>
&gt;<br>
&gt; Also, the embedded IO language does not have this property.<br>
&gt;<br>
&gt;     do x &lt;- m ; f x x<br>
&gt;<br>
&gt; is different from<br>
&gt;<br>
&gt;     do x &lt;- m ; y &lt;- m ; f x y<br>
&gt;<br>
<br>
</div>In fact IO IS referentially transparent; do NOT FORGET that there is<br>
some syntactic sugar:<br>
<div class="im"><br>
  do x &lt;- m ; f x x<br>
</div>= (&gt;&gt;=) m (\x -&gt; f x x)<br>
<div class="im"><br>
  do x &lt;- m ; y &lt;- m ; f x y<br>
</div>= (&gt;&gt;=) m (\x -&gt; (&gt;&gt;=) m (\y -&gt; f x y))<br>
<br>
So when we desugar it (and it is only desugaring, it is no<br>
optimization/reduction/whatEverElseYouWant; these two expressions have<br>
the same AST once parsed), where would you want to put referential<br>
transparency?<br>
<div class="im"><br>
&gt; and so on. This is why you shouldn&#39;t write your whole program with IO<br>
&gt; functions; it lacks nice properties for working with your code. But<br>
&gt; the embedded IO language lacking this property should not be confused<br>
&gt; with Haskell lacking this property.<br>
<br>
</div>It is not an &quot;embedded IO language&quot;, it is just some sugar for monads;<br>
you can as well do:<br>
<br>
maybePlus :: (Mabe Int) -&gt; (Maybe Int) -&gt; Maybe Int<br>
maybePlus mx my = do x &lt;- mx<br>
                     y &lt;- my<br>
                     return $ x+y<br>
<br>
and there is absolutely no IO.<br>
<div class="HOEnZb"><div class="h5"><br>
&gt;<br>
&gt; Anyhow, here&#39;s my point: these properties can be grounded in useful<br>
&gt; features of the language. However, for the vast majority of people,<br>
&gt; being able to factor their code differently and have it appear exactly<br>
&gt; the same to someone with a memory sniffer isn&#39;t useful. And unless<br>
&gt; you&#39;re doing serious crypto or something, there is no correct amount<br>
&gt; of heat for a program to produce. So if we&#39;re wondering about whether<br>
&gt; we should define purity or referential transparency to incorporate<br>
&gt; these things, the answer is an easy, &quot;no.&quot; We throw out the<br>
&gt; possibility that &#39;e + e&#39; may do more work than &#39;(\x -&gt; x + x) e&#39; for<br>
&gt; the same reason (indeed, we often want to factor it so that it<br>
&gt; performs better, while still being confident that it is in some sense<br>
&gt; the same program, despite the fact that performing better might by<br>
&gt; some definitions mean that it isn&#39;t the same program).<br>
&gt;<br>
&gt; But the stuff that shows up on stdout/stderr typically is something we<br>
&gt; care about, so it&#39;s sensible to include that. If you don&#39;t care what<br>
&gt; happens there, go ahead and use Debug.Trace. It&#39;s pure/referentially<br>
&gt; transparent modulo stuff you don&#39;t care about.<br>
&gt;<br>
&gt; -- Dan<br>
&gt;<br>
&gt; _______________________________________________<br>
&gt; Haskell-Cafe mailing list<br>
&gt; <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
&gt; <a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
<br>
<br>
_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/haskell-cafe" target="_blank">http://www.haskell.org/mailman/listinfo/haskell-cafe</a><br>
</div></div></blockquote></div><br>