Hi there, I found I can't generate a random float number(between 0 to 1) use the following method. ***************************************************************** module Main where import System(getArgs) import Random uni :: Float uni = head (randoms g) where g = mkStdGen 77 main = print (show (uni)) ********************************************** once I run it, it will generate a float number. When I run it again, it genetrate the same result. I think maybe the cause is that the seed is 77. To solve this, I think the seed should be replaced by current time .But I don't know how to capture the time. I referenced the relevant library, but I still have no idea. Who know the solution, please give me a hand. Thank you very much. Kevin Xu
It's relatively simple. The random number generator is a pure function, so it cannot be nondeterministic. So, you have a way to build this function with a seed, since the author wanted you to be able to do so, I could say for completeness, or reuse sake. But what you want is nondeterminism. How can you get that? With I/O of course. So, apart from the fact I am not going to search the "getTime" function, but it's probable haskell has one, and apart from the fact that getTime is also nondeterministic, here's a program that prints a true random number. Since this program uses I/O, it's a monadic action. import Random main = do a <- newStdGen print (head (randoms a) :: Float) The correct initializator, as one can *suppose* (but not be sure) from its type, is newStdGen. Hope this helps Vincenzo Ciancia
On Tue, 23 Jul 2002, Nick Name wrote:
It's relatively simple.
The random number generator is a pure function, so it cannot be nondeterministic. So, you have a way to build this function with a seed, since the author wanted you to be able to do so, I could say for completeness, or reuse sake.
But what you want is nondeterminism. How can you get that? With I/O of course. So, apart from the fact I am not going to search the "getTime" function, but it's probable haskell has one, and apart from the fact that getTime is also nondeterministic, here's a program that prints a true random number. Since this program uses I/O, it's a monadic action.
You shouldn't _need_ to be in the IO monad to get random numbers (although if you choose to that can be a good choice). Clearly there's the need to initialise the generator, but if you want `random' random numbers (as opposed to a known sequence of random numbers for debugging) getting the value of time via an unsafePerformIO is as good as anything else. From then on, the pseudo-random number generator will deterministically produce what are hopefully `acceptably random looking' numbers. As I made some (frankly rather confused) contribution to the debate that led to the current formulation of Random.hs, I'll have a go at explaining the intended usage. Supposing you wanted a program that generated a list of random names from a preset list, then you could have f :: [Int] -> [Name] -> [Name] f xs names = map (\x->names!!x) xs where you supply a (lazily generated) infinite list of random integers in xs. This is good because by changing the initialisation of the function generating the lazy list, you can get reliably __the same random list__ for debugging purposes. The problem comes if you've got, e.g., a need to generate two random lists: a good solution is clearly something along the lines of g::[Int]->[Name]->[Name]->([Name],[Name]) g xs names1 names2 = (f ys names1,f zs names2) where (ys,zs) = `two statistically independent random list generated from xs' The problem is to find a convenient way to split up the original list for passing to sub functions where not only are the pieces independent as complete lists, but also that no matter what pattern of further splitting the subfunctions use all pairs below are statistically independent. The idea used in the Randoms library is to have an abstract data-type StdGen which you can apply `randoms' to to get an infinite list of random numbers and which you can (deterministically) `split' into two new StdGen's which should give statistically independent sequences. With these you should get (i) the ability to write programs by passing around either generators or infinite lists, so that you can set them to produce the same results each time for debugging purposes. (ii) no need for the IO monad to infect functions purely because the need random numbers. I don't know the answer to the original posters question; however Randoms.hs contains primitive getRandomSeed :: IO Integer which I believe you can use either to get the seed within the IO monad directly or via unsafePerformIO if you don't want the IO monad around. HTH, ___cheers,_dave_________________________________________________________ www.cs.bris.ac.uk/~tweed/ | `It's no good going home to practise email:tweed@cs.bris.ac.uk | a Special Outdoor Song which Has To Be work tel:(0117) 954-5250 | Sung In The Snow' -- Winnie the Pooh
On Tue, 23 Jul 2002 16:46:37 +0100 (BST) "D. Tweed" <tweed@compsci.bristol.ac.uk> wrote:
which I believe you can use either to get the seed within the IO monad directly or via unsafePerformIO if you don't want the IO monad around.
That's true. I just prefer to have the IO monad around, for the purposes it's been designed to. That can be a matter of choice. Vincenzo Ciancia
You shouldn't _need_ to be in the IO monad to get random numbers (although if you choose to that can be a good choice). Clearly there's the need to initialise the generator, but if you want `random' random numbers (as opposed to a known sequence of random numbers for debugging) getting the value of time via an unsafePerformIO is as good as anything else. From then on, the pseudo-random number generator will deterministically produce what are hopefully `acceptably random looking' numbers.
Isn't this a very dangerous practice? It's so very, very easy to break referential transparency when using unsafePerformIO with functions known to produce observably different results each time you call it. And once you do this, all kinds of nice Haskell properties go to hell. Safer ways would be to use the monadic operators as intended to get random seeds and then use implicit parameters to pass them around (using a mild variation of John Hughes' approach to mutable variables). -- Alastair Reid alastair@reid-consulting-uk.ltd.uk Reid Consulting (UK) Limited http://www.reid-consulting-uk.ltd.uk/alastair/
On 23 Jul 2002, Alastair Reid wrote:
You shouldn't _need_ to be in the IO monad to get random numbers (although if you choose to that can be a good choice). Clearly there's the need to initialise the generator, but if you want `random' random numbers (as opposed to a known sequence of random numbers for debugging) getting the value of time via an unsafePerformIO is as good as anything else. From then on, the pseudo-random number generator will deterministically produce what are hopefully `acceptably random looking' numbers.
Isn't this a very dangerous practice? It's so very, very easy to break referential transparency when using unsafePerformIO with functions known to produce observably different results each time you call it. And once you do this, all kinds of nice Haskell properties go to hell.
I would imagine it's an incredibly dangerous practice; I've only actually done this for top level CAFs, and I'd imagine these are probably much less likely to be duplicated by optimisation which is why it hasn't bitten me. In general I do get the seed in a top level IO monad wrapper.
Safer ways would be to use the monadic operators as intended to get random seeds and then use implicit parameters to pass them around (using a mild variation of John Hughes' approach to mutable variables).
That sounds a good way (implicit parameters are on my `learn about at some point list'). All I was trying to say, in my rather confused email, is that __one__ haskell idiom for dealing with random numbers is by passing around StdGen's, in contrast with the C idiom of `calling a random number generator function' and that if you pass in an initial StdGen you don't need to be within the IO monad to do processing involving random numbers. It wasn't clear to me whether Vincenzo's e-mail was saying that you just needed to be in IO to generate the seed or that you need to be in IO to do anything that involves generating random numbers __after you've got the seed__. Since I have to admit I really dislike having monads extend beyond the top couple of levels of a program I wanted to point out that actually generating and using random numbers can be done outside IO. ___cheers,_dave_________________________________________________________ www.cs.bris.ac.uk/~tweed/ | `It's no good going home to practise email:tweed@cs.bris.ac.uk | a Special Outdoor Song which Has To Be work tel:(0117) 954-5250 | Sung In The Snow' -- Winnie the Pooh
On Wed, 24 Jul 2002 10:44:51 +0100 (BST) "D. Tweed" <tweed@compsci.bristol.ac.uk> wrote:
It wasn't clear to me whether Vincenzo's e-mail was saying that you just needed to be in IO to generate the seed or that you need to be in IO to do anything that involves generating random numbers __after you've got the seed__. Since I have to admit I really dislike having monads extend beyond the top couple of levels of a program I wanted to point out that actually generating and using random numbers can be done outside IO.
Well, what I meant is that, being Haskell a lazy pure functional language, the *right* way to use I/O and nondeterminism in general is the IO monad. You can avoid it by using unsafeSomething but... it's unsafe. I like haskell the way it is. If one wants to write pure code using a random number generator created with newStdGen, which is in the IO monad, it's easy, he/she just writes a pure function "f" whose argument is a random number generator. And then the random number generator is created in the IO monad and "f" is applied to it. Vincenzo
participants (4)
-
Alastair Reid -
D. Tweed -
Junjie Xu -
Nick Name