Re: [Haskell-cafe] Just how unsafe is unsafe

2009-02-08 Thread Yitzchak Gale
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

2009-02-07 Thread Yitzchak Gale
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

2009-02-06 Thread Edsko de Vries
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

2009-02-05 Thread Andrew Wagner
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

2009-02-05 Thread Jonathan Cast
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

2009-02-05 Thread Jake McArthur

-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

2009-02-05 Thread Peter Verswyvelen
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-02-05 Thread Max Rabkin
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

2009-02-05 Thread Jake McArthur

-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

2009-02-05 Thread Peter Verswyvelen
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