繁体   English   中英

在Haskell中生成随机数

[英]Random number generating in haskell

当运行genRandTupe我不断获得相同的随机数,但是当运行genrandListgen为参数时,每次都会得到一组新的数字。 我该如何解决? 为什么g = newStdGen生成新的随机数?

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是一个常量应用形式 这意味着在任何局部变量letwhere块memoised。 通常很方便的壮举!

在您的情况下,这意味着列表[a,b]在整个程序中仅计算一次。 计算方式实际上是非法的( 不要使用unsafePerformIO !),但这并不重要,因为它只会发生一次。 将这个常量元组包装到IOreturn ,实际上是完全多余的,您也可以写

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

OTOH,当您在多个单独的位置评估genrandList gen (不是CAF)时,结果不一定会存储。 取而代之的是,使用unsafePerformIO 不安全地修改全局状态来重新计算该函数(或者可能不会...编译器实际上可以自由地对此进行优化,因为您知道genRandList应该是纯函数...),因此产生每次都有不同的结果。

当然,正确的做法是远离unsafePerformIO 实际上,根本不需要在genRandList执行IO,因为它已经接受了随机生成器...只需在传递它之前将其与IO绑定即可:

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)

请注意,因为let [a,b] = ...现在在do块中,所以它现在在IO monad中,与genRandTupe''的CAF genRandTupe''

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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