我有一个函数,它采用一系列随机数/浮点数,并使用它们来生成一个值/结构(即,采用随机速度和球被抛出的点的位置并输出它会降落的坐标) . 我需要连续生成数千个。
我实现所有东西的方式是每个计算都接受一个 stdGen,用它来生成几个数字,并传递一个新的 stdGen 以允许它链接到另一个。
为了对 10000 个项目执行此操作,我制作了一个列表,generate_item n
从中基本上输出一个(value,gen)
元组(该值是我要计算的值),其中的值gen
是从获取的计算中递归输出的 stdGen值来自generate_item n-1
但是,该程序在大约一千个结果左右时似乎爬行得慢得不切实际。而且似乎绝对不可扩展。这可能与我将所有generate_item
结果都存储在内存中这一事实有关吗?
或者有没有比我上面描述的更惯用的方法在 Haskell 中使用 Monads 或其他方法来解决这个问题?
请注意,即使在 ruby 和 python 等高级脚本语言中,从随机值生成算法的代码也会在几秒钟内生成 10k;这些计算几乎不密集。
代码
-- helper functions that take in StdGen and return (Result,new StdGen)
plum_radius :: StdGen -> (Float,StdGen)
unitpoint :: Float -> StdGen -> ((Float,Float,Float),StdGen)
plum_speed :: Float -> StdGen -> (Float,StdGen)
-- The overall calculation of the value
plum_point :: StdGen -> (((Float,Float,Float),(Float,Float,Float)),StdGen)
plum_point gen = (((px,py,pz),(vx,vy,vz)),gen_out)
where
(r, gen2) = plum_radius gen
((px,py,pz),gen3) = unitpoint r gen2
(s, gen4) = plum_speed r gen3
((vx,vy,vz),gen5) = unitpoint s gen4
gen_out = gen5
-- Turning it into some kind of list
plum_data_list :: StdGen -> Int -> (((Float,Float,Float),(Float,Float,Float)),StdGen)
plum_data_list seed_gen 0 = plum_point seed_gen
plum_data_list seed_gen i = plum_point gen2
where
(_,gen2) = plum_data_list seed_gen (i-1)
-- Getting 100 results
main = do
gen <- getStdGen
let data_list = map (plum_data_list gen) [1..100]
putStrLn List.intercalate " " (map show data_list)