
On Thursday 11 November 2010 11:54:56 am Sjoerd Visscher wrote:
Yes, but it would not break any existing code. It would only break code that knowingly did the wrong thing.
Well, if we added a function that randomly scrambled GHC's heap memory, it wouldn't break any existing code, because none would use it. :)
We already have a weak case of this, since (\x -> undefined x) can be distinguished from undefined using seq, but that can be hand-waved away by not worrying about bottoms so much. That isn't going to work for serialize.
Why not?
Because, there is an argument to be made in the seq case that no one really cares about the differences it introduces. I don't usually care how my code works on bottoms, except inasmuch as it determines various performance characteristics of the code*, or whether it works on infinite values. I try, generally speaking, to write total functions, and run them on well-defined inputs. So when I reason about the programs, it is this aspect that I care most about, not about what happens when I feed in undefineds. There are even folks that have worked on making this perspective rigorous. See, Fast and Loose Reasoning is Morally Correct. serialize is not at all the same in this regard. There is no class of functions that is immune to its inspection powers, presumably, because that's its whole point. But that also means that there is no class of functions for which we are justified in reasoning equationally using the standard extensional equality. The only way that would be justified is saying, "serialize doesn't exist."
Then don't do that. Being able to serialize functions is just as dangerous as having unsafePerformIO. If you don't use it, you don't have problems.
And unsafePerformIO's very name suggests that you're breaking things when you use it. It comes with lots of caveats, and the Haskell community will generally heap scorn on you if you use it for trivialities (or even non- trivialities). I don't understand why it would be desirable for a serialize function to be branded, "don't ever use this unless you're an expert who knows what he's doing." unsafePerformIO is, for many uses, a concession to low-level compiler extensibility. You can implement a fair amount of stuff in a library using unsafePerformIO that would otherwise require some kind of compiler support. What is the analogous motivation for functions to be turned into pure strings containing their code? Of course, if you want, "everything is unsafe, be careful," there are many, many languages out there that already do that. For instance, ML**, Lisp, C, Java, Python, .... But this is Haskell, and we try to do a little better than that. -- Dan [*] Which is irrelevant to the reasoning in question. In fact, if you follow Bird's methodology, you first write a naive, obviously correct program, and then you transform it into a more efficient version via transformations you've shown to preserve semantics. This approach doesn't work if there are no correctness-preserving transformations, though. [**] In fact, Alice ML (I think that's the right one) already has very fancy serialization stuff. You can store and load and send entire modules over an internet connection, I believe.