This thread pretty much exemplifies why many people don'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"><<a href="mailto:sedrikov@gmail.com">sedrikov@gmail.com</a>></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 <<a href="mailto:dan.doel@gmail.com">dan.doel@gmail.com</a>> a écrit :<br>
<div class="im"><br>
> On Sun, Jan 1, 2012 at 3:26 PM, Ketil Malde <<a href="mailto:ketil@malde.org">ketil@malde.org</a>> wrote:<br>
> > Chris Smith <<a href="mailto:cdsmith@gmail.com">cdsmith@gmail.com</a>> writes:<br>
> ><br>
> >>> I wonder: can writing to memory be called a “computational<br>
> >>> effect”? If yes, then every computation is impure.<br>
> ><br>
> > I wonder if not the important bit is that pure computations are<br>
> > unaffected by other computations (and not whether they can affect<br>
> > other computations). Many pure computations have side effects<br>
> > (increases temperature, modifies hardware registers and memory,<br>
> > etc), but their effect can only be observed in IO.<br>
> ><br>
> > (E.g. Debug.Trace.trace provides a non-IO interface by use of<br>
> > unsafePerformIO which is often considered cheating, but in<br>
> > this view it really is pure.)<br>
><br>
> The point of purity (and related concepts) is to have useful tools for<br>
> working with and reasoning about your code. Lambda calculi can be seen<br>
> as the prototypical functional languages, and the standard ones have<br>
> the following nice property:<br>
><br>
> The only difference between reduction strategies is termination.<br>
><br>
> Non-strict strategies will terminate for more expressions than strict<br>
> 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>
><br>
> This property is often taken to be the nub of what it means to be a<br>
> pure functional language. If the language is an extension of the<br>
> lambda calculus that preserves this property, then it is a pure<br>
> functional language. Haskell with the 'unsafe' stuff removed is such a<br>
> language by this definition, and most GHC additions are too, depending<br>
> on how you want to argue. It is even true with respect to the output<br>
> of programs, but not when you're using Debug.Trace, because:<br>
><br>
> flip (+) ("foo" `trace` 1) ("bar" `trace` 1)<br>
><br>
> will print different things with different evaluation orders.<br>
><br>
> A similar property is referential transparency, which allows you to<br>
> factor your program however you want without changing its denotation.<br>
> So:<br>
><br>
> (\x -> x + x) e<br>
><br>
> is the same as:<br>
><br>
> e + e<br>
><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>
> This actually fails for strict evaluation strategies unless you relax<br>
> it to be 'same denotation up to bottoms' or some such. But not having<br>
> to worry about whether you're changing the definedness of your<br>
> programs by factoring/inlining is actually a useful property that<br>
> 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>
><br>
> Also, the embedded IO language does not have this property.<br>
><br>
> do x <- m ; f x x<br>
><br>
> is different from<br>
><br>
> do x <- m ; y <- m ; f x y<br>
><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 <- m ; f x x<br>
</div>= (>>=) m (\x -> f x x)<br>
<div class="im"><br>
do x <- m ; y <- m ; f x y<br>
</div>= (>>=) m (\x -> (>>=) m (\y -> 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>
> and so on. This is why you shouldn't write your whole program with IO<br>
> functions; it lacks nice properties for working with your code. But<br>
> the embedded IO language lacking this property should not be confused<br>
> with Haskell lacking this property.<br>
<br>
</div>It is not an "embedded IO language", it is just some sugar for monads;<br>
you can as well do:<br>
<br>
maybePlus :: (Mabe Int) -> (Maybe Int) -> Maybe Int<br>
maybePlus mx my = do x <- mx<br>
y <- my<br>
return $ x+y<br>
<br>
and there is absolutely no IO.<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
> Anyhow, here's my point: these properties can be grounded in useful<br>
> features of the language. However, for the vast majority of people,<br>
> being able to factor their code differently and have it appear exactly<br>
> the same to someone with a memory sniffer isn't useful. And unless<br>
> you're doing serious crypto or something, there is no correct amount<br>
> of heat for a program to produce. So if we're wondering about whether<br>
> we should define purity or referential transparency to incorporate<br>
> these things, the answer is an easy, "no." We throw out the<br>
> possibility that 'e + e' may do more work than '(\x -> x + x) e' for<br>
> the same reason (indeed, we often want to factor it so that it<br>
> performs better, while still being confident that it is in some sense<br>
> the same program, despite the fact that performing better might by<br>
> some definitions mean that it isn't the same program).<br>
><br>
> But the stuff that shows up on stdout/stderr typically is something we<br>
> care about, so it's sensible to include that. If you don't care what<br>
> happens there, go ahead and use Debug.Trace. It's pure/referentially<br>
> transparent modulo stuff you don't care about.<br>
><br>
> -- Dan<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>
<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>