一連の乱数/フロートを取得し、それらを使用して値/構造を生成する関数があります(つまり、ランダムな速度とボールが投げられたポイントの位置を取得し、着地する座標を出力します) . そして、数千を連続して生成する必要があります。
私がすべてを実装した方法は、各計算が stdGen を受け取り、それを使用していくつかの数値を生成し、新しい stdGen を渡して別の数値にチェーンできるようにすることです。
10000 個のアイテムに対してこれを行うには、generate_item n
基本的に(value,gen)
タプル (値は計算しようとしている値) を出力する一種のリストを作成しますgen
。からの値generate_item n-1
ただし、このプログラムは約 1,000 件程度の結果で非現実的な速度でクロールするようです。そして、間違いなくスケーラブルではないようです。すべてのgenerate_item
結果をメモリに保存しているという事実と関係があるのでしょうか?
それとも、私が上で説明したものよりも、Monads などを使用して Haskell でこの問題にアプローチする、より慣習的な方法はありますか?
ランダム値からアルゴリズムを生成するコードは、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)