Re: [Haskell-cafe] Just how unsafe is unsafe
Peter Verswyvelen wrote: I do have asked myself the question whether a really random generating function could be regarded as pure somehow I wrote: Not really... Alberto G. Corona wrote: What is pure randomness? .When the algorithmic complexity of the list of random number is equal to the lenght of the list, that is, is incompressible by any means. But this can not be probed. the distribution of values gives a hint of whether if the list obey any algorithm, but even so, many compressible series have a random distribution. in practical terms, it is random has a random distribution, the receiver does not know the algorithm AND the initial value. In this case it can be pure. Perhaps philosophically you can consider it pure, but it is unsafe to treat it as pure in your program. If you write x = genRandomR (1, 100) then the compiler may or may not replace the variable x by the function application genRandomR (1, 100) anywhere in your program. That is probably not what you want. -Yitz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
Peter Verswyvelen wrote: I do have asked myself the question whether a really random generating function could be regarded as pure somehow Not really. Somewhere in your program you are likely to make the assumption that a value you obtained, however indirectly, from this function will be the same in two different places. But the sands will constantly be shifting. Furthermore, in real life physical RNGs also involve state, because they need to accumulate entropy. For example, in Unix (on many platforms), the physical RNG device /dev/random will block until there is enough entropy to provide a random number. The /dev/urandom device always returns a number immediately, but that is because it will return a pseudo-random number if there is not enough entropy available, again requiring state. -Yitz ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
Hi, My opinion is that unsafeXXX is acceptable only when its use is preserved behind an abstraction that is referentially transparent and type safe. Others may be able to help refine this statement. I would agree with this. The problem is that impurity spreads easily. For example, suppose we have this truly random number generator, 'random'. As soon as we have this, then *almost every* function is potentially impure: f :: Integer - Integer f x = random + x g :: [Integer] g = repeat random etc. etc. The compiler has no way of tracking impurity other than through the type system which is, of course, exactly what monads do. To echo the sentiment above, the only safe way to use unsafePerformIO is to hide it behind a function that *is* guaranteed to be pure (i.e., returns the same values for the same arguments, can be inlined, etc.). And even then, I would recommend against it. Let me give a *practical* reason why. For a long time, I would never even have considered unsafePerformIO, but I recently had an application that needed unique global identifiers in lots of places, and I was reluctant to pass state around everywhere; *but* I could hide it in a few functions, which were themselves pure. It looked something like: -- Replace (some) name by a number quote :: Integer - Term - Term -- Replace a number by (that) name unquote :: Name - Term - Term -- Typical usage foo t == let l = getUnsafeUniqueGlobalIdentifier () in unquote l . do some stuff . quote l Since unquote l . quote l is an identity operation, 'foo' itself is pure -- provided that nothing in 'do some stuff' relies on the exact identity of the identifier. --- A rule which I broke at some point, got some very strange behaviour, and took me ages to debug. This was mostly due to laziness, which made the point of execution of the unsafe operation to be very difficult to predict. For example, every call to getUnsafeUniqueGlobalIdentifier (it wasn't actually called that, don't worry :-) yielded a number one higher than the previous. However, in a list of terms [t1, t2, .., tn] all of which include some unique idnetifier, it is *not* the generation of the list that determines whether the identifiers in these terms are incrementing, but the *evaluation* of the list -- when are the terms forced to normal form. I was called 'sort' on this list, and sort depended on the values of these identifiers -- but since sort evaluated the terms in the list to normal form in a hard to predict order, the order of the list was anything but sorted! --- Moreover, you need all sorts of compiler options or nasty hacks (the unit argument to getUnsafeUniqueGlobalIdentifier above is no mistake) to avoid the compiler optimizing your code in ways that you did not expect. In the end, I ended up rewriting the entire application to avoid the use of this global unique identifiers, because it was simply too difficult to get right. I felt I was writing C code again and was chasing bugs due to dangling pointers and the wrong memory being used. Not a time I want to return to! Moral of the story: unless you really really need to and really really know what you are doing -- do not use unsafePerformIO. Uncontrolled side effects and lazines will cause extremely hard to track behaviour in your program, and things are almost guaranteed to go wrong. Edsko ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Just how unsafe is unsafe
So we all know the age-old rule of thumb, that unsafeXXX is simply evil and anybody that uses it should be shot (except when it's ok). I understand that unsafeXXX allows impurity, which defiles our ability to reason logically about haskell programs like we would like to. My question is, to what extent is this true? Suppose we had a module, UnsafeRandoms, which had a function that would allow you to generate a different random number every time you call it. The semantics are relatively well-defined, impurity is safely sectioned off in its own impure module, which is clearly labeled as such. How much damage does this do? Can we push the lines elsewhere? Is sectioning unsafeXXX into Unsafe modules a useful idiom that we can use for other things as well? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
On Thu, 2009-02-05 at 16:11 -0500, Andrew Wagner wrote: So we all know the age-old rule of thumb, that unsafeXXX is simply evil and anybody that uses it should be shot (except when it's ok). I understand that unsafeXXX allows impurity, which defiles our ability to reason logically about haskell programs like we would like to. Not just that! Parametric polymorphism is unsound in combination with mutable values; but unsafePerformIO turns on exactly that combination. unsafeCoerce :: alpha - beta unsafeCoerce x = unsafePerformIO $ do let r = unsafePerformIO $ newIORef undefined r `writeIORef` x readIORef r My question is, to what extent is this true? unsafePerformIO is a true function --- in the absence of any fancy compiler trickery --- on a small subset of its domain. Outside of that subset, I would regard use of unsafePerformIO simply as a bug --- violation of an unchecked precondition. Period. Suppose we had a module, UnsafeRandoms, which had a function that would allow you to generate a different random number every time you call it. unsafePerformIO does not allow you to guarantee this! If I defined myRandomNumber = unsafePerformIO $ randomNumber then the compiler is permitted to call randomNumber (at most) *once*, and use that number throughout the program. The semantics are relatively well-defined, Leaving aside the issue above, I would think complete randomness was nearly the worst possible case, semantically. (The *worst* worst possible case would be non-statistical non-determinism --- which is what you actually get here). impurity is safely sectioned off in its own impure module, which is clearly labeled as such. How much damage does this do? Well, it forces me to chase your libraries import lists to decide whether I want to trust your code, for one thing. Haskell is all about making it easier to audit code, not harder. Can we push the lines elsewhere? I'd rather not. Is sectioning unsafeXXX into Unsafe modules a useful idiom that we can use for other things as well? I'd rather not write other unsafe functions at all. Sectioning off things that need to be unsafe into pure solutions --- like, say, monads --- is a much better idea. (Go read the global variables thread from last year). jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Andrew Wagner wrote: | I understand that unsafeXXX allows impurity, which defiles our ability | to reason logically about haskell programs like we would like to. My | question is, to what extent is this true? My opinion is that unsafeXXX is acceptable only when its use is preserved behind an abstraction that is referentially transparent and type safe. Others may be able to help refine this statement. | Suppose we had a module, UnsafeRandoms, which had a function that would | allow you to generate a different random number every time you call it. | The semantics are relatively well-defined, impurity is safely sectioned | off in its own impure module, which is clearly labeled as such. How much | damage does this do? This does not preserve referential transparency, so by my criteria above this is an unacceptable use of an unsafe function. One reason it's a bad idea is that it removes determinism, which may be very important for testability. - - Jake -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmLW/MACgkQye5hVyvIUKniOACfQGPLiY65+eiMfsv7BlbYLI++ Bd0An1N5wp6TDkJzhmdw831/Gj45Bv9S =TnQg -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
I do have asked myself the question whether a really random generating function could be regarded as pure somehow (actually would a true random function still be a mathematical function?) E.g. the function would return a true (not pseudo) random number, practically unpredictable (e.g. hardware assisted, using some physical phenomenon, e.g. using atmospheric noise or something). So you surely won't get referential transparency but since the function is really random, this would be correct behavior? Of course you could just put this random generator in the IO monad, but certain algorithms- like Monte Carlo - intuitively don't seem to operate in a IO monad to me. Okay, just some thoughts from someone who knows absolutely nothing about category theory or advanced computer science, so don't shoot me ;-) On Thu, Feb 5, 2009 at 10:36 PM, Jake McArthur j...@pikewerks.com wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Andrew Wagner wrote: | I understand that unsafeXXX allows impurity, which defiles our ability | to reason logically about haskell programs like we would like to. My | question is, to what extent is this true? My opinion is that unsafeXXX is acceptable only when its use is preserved behind an abstraction that is referentially transparent and type safe. Others may be able to help refine this statement. | Suppose we had a module, UnsafeRandoms, which had a function that would | allow you to generate a different random number every time you call it. | The semantics are relatively well-defined, impurity is safely sectioned | off in its own impure module, which is clearly labeled as such. How much | damage does this do? This does not preserve referential transparency, so by my criteria above this is an unacceptable use of an unsafe function. One reason it's a bad idea is that it removes determinism, which may be very important for testability. - - Jake -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmLW/MACgkQye5hVyvIUKniOACfQGPLiY65+eiMfsv7BlbYLI++ Bd0An1N5wp6TDkJzhmdw831/Gj45Bv9S =TnQg -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
2009/2/5 Peter Verswyvelen bugf...@gmail.com: Of course you could just put this random generator in the IO monad, but certain algorithms- like Monte Carlo - intuitively don't seem to operate in a IO monad to me. For PRNGs, only State is needed, not IO. But you might find the `randoms' function useful: it returns in infinite list of pseudo-random values. --Max ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Peter Verswyvelen wrote: | I do have asked myself the question whether a really random generating | function could be regarded as pure somehow (actually would a true | random function still be a mathematical function?) | | E.g. the function would return a true (not pseudo) random number, | practically unpredictable (e.g. hardware assisted, using some physical | phenomenon, e.g. using atmospheric noise or something). So you surely | won't get referential transparency but since the function is really | random, this would be correct behavior? An informal definition of a function might be something like a black box that takes and input and produces an output, and for each possible input, the output must be the same. Taking this to be a function, there is really no such thing as a random function, and if there was, it wouldn't even need to be a function. (What would the input to it be?) If you wanted to mathematically represent a random number, it would, in most cases I can think of, best be represented as a free variable. In a program, such a free variable could be filled in by the runtime. Conveniently, (and by no coincidence) this is something the IO monad can provide for us! :) | Of course you could just put this random generator in the IO monad, but | certain algorithms- like Monte Carlo - intuitively don't seem to operate | in a IO monad to me. Why not? A Random monad might be more appropriate in this case anyway. Such a monad is a State monad that hold a random seed. Every time a random number is needed, the seed is passed to a deterministic psuedo-random number generator, and a new seed is put as the next state. If a truly random number is ever needed, either IO or unsafeInterleaveIO will be needed. The use of unsafeInterleaveIO would be a (rightly) controversial choice though. - - Jake -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmLaK4ACgkQye5hVyvIUKk88QCfRksu7z80QmzgjUvmiyrzDDjl QnsAn1R5DHz2tJpWP3yb0+U+loyBdyCX =RIX9 -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Just how unsafe is unsafe
Well, one could say that a truly random number function takes as input time and some constant unique identifier (serial number) of the TRND device and gives you the random value measured at that time by this device. Of course this would mean the random value is not really random, since the potential creator of the universe would have known the value already, but to all humble beings living in the bubble, it would be Truly Random :) Then the question is, is time a function? If so, is it discrete? Okay, this is not Haskell anymore, this would become philosophy, and since a good and smart friend of mine told me that nobody really knows what time is, this is off topic. Sorry! :) On Thu, Feb 5, 2009 at 11:31 PM, Jake McArthur j...@pikewerks.com wrote: -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Peter Verswyvelen wrote: | I do have asked myself the question whether a really random generating | function could be regarded as pure somehow (actually would a true | random function still be a mathematical function?) | | E.g. the function would return a true (not pseudo) random number, | practically unpredictable (e.g. hardware assisted, using some physical | phenomenon, e.g. using atmospheric noise or something). So you surely | won't get referential transparency but since the function is really | random, this would be correct behavior? An informal definition of a function might be something like a black box that takes and input and produces an output, and for each possible input, the output must be the same. Taking this to be a function, there is really no such thing as a random function, and if there was, it wouldn't even need to be a function. (What would the input to it be?) If you wanted to mathematically represent a random number, it would, in most cases I can think of, best be represented as a free variable. In a program, such a free variable could be filled in by the runtime. Conveniently, (and by no coincidence) this is something the IO monad can provide for us! :) | Of course you could just put this random generator in the IO monad, but | certain algorithms- like Monte Carlo - intuitively don't seem to operate | in a IO monad to me. Why not? A Random monad might be more appropriate in this case anyway. Such a monad is a State monad that hold a random seed. Every time a random number is needed, the seed is passed to a deterministic psuedo-random number generator, and a new seed is put as the next state. If a truly random number is ever needed, either IO or unsafeInterleaveIO will be needed. The use of unsafeInterleaveIO would be a (rightly) controversial choice though. - - Jake -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkmLaK4ACgkQye5hVyvIUKk88QCfRksu7z80QmzgjUvmiyrzDDjl QnsAn1R5DHz2tJpWP3yb0+U+loyBdyCX =RIX9 -END PGP SIGNATURE- ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe