我有以下代码(试图模拟高斯随机游动):
import System.Random
import Control.Applicative
getStdNormal :: StdGen -> (Float,StdGen)
getStdNormal g = let l = drop 1 . take 49 $ iterate (\(_,g') -> random g') (0,g) in
((/ 2) . (+ (-24)) . sum . map fst $ l, snd . last $ l)
mphi = getStdRandom getStdNormal
l1 = setStdGen (mkStdGen 20180916) >> (sequence . take 10 $
iterate (\s -> (\a -> \b -> b) <$> s <*> mphi) (return 0))
l2 = setStdGen (mkStdGen 20180916) >> (sequence . take 10 $
iterate (\s -> (\a -> \b -> a + b) <$> s <*> mphi) (return 0))
正如我所期望的, l1
被评估为(显然是正常的)随机值列表:
[0.0,1.1155739,-0.24667645,0.7793722,-0.18391132,0.23517609,-0.80208874,-1.5305595,-0.28670216,0.53894806]
但是,l2
的表现与我的预期相去甚远。该列表显然不是l1
部分和的序列,并且极不可能具有标准的正态差异:
[0.0,1.1155739,0.55951977,0.22015285,-2.0858078,0.6170025,-5.20298,0.3877325,1.410594,0.8647003]
(请注意,前两个成员是正确的。)实际上,尽管我倾向于指责l2
中的懒惰,但我无法解释mphi
中数字的来源。 / p>
为什么代码不能按预期工作?非常感谢!
答案 0 :(得分:1)
以下是iterate (\s -> (\a b -> b) <$> s <*> mphi) (return 0)
的前几个元素:
return 0
(\a b -> b) <$> return 0 <*> mphi
(\a b -> b) <$> ((\a b -> b) <$> return 0 <*> mphi) <*> mphi
(\a b -> b) <$> ((\a b -> b) <$> ((\a b -> b) <$> return 0 <*> mphi) <*> mphi) <*> mphi
对这些序列进行排序时,会得到以下结果:
do
v0 <- return 0
v1 <- (\a b -> b) <$> return 0 <*> mphi
v2 <- (\a b -> b) <$> ((\a b -> b) <$> return 0 <*> mphi) <*> mphi
v3 <- (\a b -> b) <$> ((\a b -> b) <$> ((\a b -> b) <$> return 0 <*> mphi) <*> mphi) <*> mphi
return [v0, v1, v2, v3]
请特别注意,这些行之间不会重置随机种子,并且\a b -> b
抛出的内容是结果值,而不是 IO
操作。这意味着我们在0
中得到了常量v0
; v1
中随机序列的第一个元素(不是v0
!); v2
中随机序列的第三个元素(完全跳过第二个元素)(这可能是您想要的,但只是偶然...); v3
中随机序列的第六个元素(不是v5
!并完全跳过序列的第四和第五个元素);依此类推,将三角形数最多,扔掉我们生成的随机数中的最多。
您几乎可以肯定想要的是
do
v0 <- mphi
v1 <- mphi
v2 <- mphi
v3 <- mphi
return [v0, v1, v2, v3]
可以通过使用repeat mphi
而不是iterate (\s -> ...) (return 0)
来实现。这使我们到达:
sequence . take 10 $ repeat mphi
习惯上,然后将take 10 (repeat mphi)
更改为replicate 10 mphi
,然后将sequence (replicate 10 mphi)
更改为replicateM 10 mphi
。
类似的注释也适用于您的求和版本:结果列表的元素n
已生成n
个随机数(与先前使用的任何一个都不相同,用于结果列表中较早的总和)并将它们相加。也许这就是您想要的,但是我怀疑您真正想要的只是:
scanl (+) 0 <$> replicateM 10 mphi