简体   繁体   中英

Random number generating in haskell

When running genRandTupe I continuously get the same random numbers, however when running genrandList with gen as the argument i get a new set of numbers every time. How would I solve this? Why doesn't g = newStdGen generate a new random number?

import System.Random
import System.IO.Unsafe

type RandTupe = (Int,Int)
genRandTupe :: IO RandTupe
genRandTupe = let [a,b] = genrandList g in return (a,b) where g = newStdGen
genrandList gen = let g = unsafePerformIO gen in take 2 (randomRs (1, 20) g)
gen = newStdGen

genRandTupe is a constant applicative form . That means any local variables in its let or where blocks are memoised. Usually quite a convenient feat!

In your case, it means that the list [a,b] is only computed once in your whole program. The way it is computed is actually illegal ( don't use unsafePerformIO !), but it doesn't really matter because it only happens once anyway. Wrapping this constant tuple then into IO with return is actually completely superfluent, you could as well have written

genRandTupe' :: RandTupe
genRandTupe' = let [a,b] = genrandList g in (a,b)
 where g = newStdGen

OTOH, when you evaluate genrandList gen (not a CAF) in multiple separate places, the result will not necessarily be stored. Instead, that function is calculated anew, using unsafePerformIO to unsafely modify the global state (or maybe not... the compiler is actually free to optimise this away since, you know, genRandList is supposedly a pure function...) and therefore yield a different result each time.

The correct thing, of course, is to stay the heck away from unsafePerformIO . There's actually no need at all to do IO in genRandList , since it already accepts a random generator... just bind that generator out from IO before passing it:

genRandTupe'' :: IO RandTupe
genRandTupe'' = do
    g <- newStdGen
    let [a,b] = genrandList g
    return (a,b)

randListFrom :: RandomGen g => g -> [Int]
randListFrom g = take 2 (randomRs (1, 20) g)

Note that, because the let [a,b] = ... now is in a do block, it's now in the IO monad, decoupled from the CAF closure of genRandTupe'' .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM