gpt4 book ai didi

haskell - Haskell和State Monad的随机数序列,我做错了什么?

转载 作者:行者123 更新时间:2023-12-03 14:07:53 27 4
gpt4 key购买 nike

作为我 Haskell 之旅的一部分,我正在实现一个光线追踪器,我需要能够在代码中的多个位置绘制随机数序列。通常我希望能够为每个像素获取 64 个样本,并且像素是并行计算的。

我正在查看 state monad 来实现这一点,我以这个答案为指导 Sampling sequences of random numbers in Haskell但我写的代码并没有终止,它的内存消耗爆炸了。

这是代码的抽象部分:
我希望能够调用sampleUniform在代码中多次获取新的随机数列表,但如果我这样做 runhaskell test.hs , 它输出 lis 的第一个字符 [然后它陷入了一个明显的无限循环。

module Main (main
, computeArray) where

import Control.Monad
import Control.Monad.State (State, evalState, get, put)
import System.Random (StdGen, mkStdGen, random)
import Control.Applicative ((<$>))

type Rnd a = State StdGen a

runRandom :: Rnd a -> Int -> a
runRandom action seed = evalState action $ mkStdGen seed

rand :: Rnd Double
rand = do
gen <- get
let (r, gen') = random gen
put gen'
return r

{- Uniform distributions -}
uniform01 :: Rnd [Double]
uniform01 = mapM (\_ -> rand) $ repeat ()

{- Get n samples uniformly distributed between 0 and 1 -}
sampleUniform :: Int -> Rnd [Double]
sampleUniform n = liftM (take n) uniform01

computeArray :: Rnd [Bool]
computeArray = do
samples1 <- sampleUniform 10
samples2 <- sampleUniform 10
let dat = zip samples1 samples2
return $ uncurry (<) <$> dat

main :: IO ()
main = do
let seed = 48
let res = runRandom computeArray seed
putStrLn $ show res

最佳答案

uniform01通过无限数量的计算将您的状态线程化,这意味着尽管它懒惰地产生结果,但没有希望在最后检索最终状态以用于下一次采样。 liftM (take n)只影响最终值,而不影响用于计算它的状态效应。因此,正如所写,您只能使用 uniform01/sampleUniform一次。

相反,您只能将状态线程化到 rand 中。您使用的操作,例如和

sampleUniform n = mapM (\_ -> rand) $ replicate n ()

或更简单
sampleUniform n = sequence $ replicate n rand

关于haskell - Haskell和State Monad的随机数序列,我做错了什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31892418/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com