在以下程序中,为什么每一行都返回True
?我原以为是因为我正在用不同的种子初始化mkStdGen
,有些行应该返回True
而其他行返回False
:
module Main where
import System.Random
main = do
--why every single line prints "True" ?
print $ fst (random (mkStdGen 1) :: (Bool, StdGen))
print $ fst (random (mkStdGen 2) :: (Bool, StdGen))
print $ fst (random (mkStdGen 3) :: (Bool, StdGen))
print $ fst (random (mkStdGen 4) :: (Bool, StdGen))
print $ fst (random (mkStdGen 5) :: (Bool, StdGen))
print $ fst (random (mkStdGen 6) :: (Bool, StdGen))
print $ fst (random (mkStdGen 7) :: (Bool, StdGen))
print $ fst (random (mkStdGen 8) :: (Bool, StdGen))
print $ fst (random (mkStdGen 9) :: (Bool, StdGen))
print $ fst (random (mkStdGen 10) :: (Bool, StdGen))
即使在源mkStdGen中,它也声明“不同的参数 应该可能产生不同的发电机“:
{- |
The function 'mkStdGen' provides an alternative way of producing an initial
generator, by mapping an 'Int' into a generator. Again, distinct arguments
should be likely to produce distinct generators.
-}
mkStdGen :: Int -> StdGen -- why not Integer ?
mkStdGen s = mkStdGen32 $ fromIntegral s
答案 0 :(得分:3)
有趣的是,这只是出现在haskell reddit(discussion here)上,并记录在this post中。文章建议从种子中丢弃第一个生成器,如:
better_mkStdGen seed = snd $ randomR (1,6) $ mkStdGen seed
或者您可以使用随机包来对分发做出一些声明,例如mwc-random。
答案 1 :(得分:3)
不是答案,但我肯定会同意jberryman并抛弃前几个值,或使用mwc-random
。如果你做了
>>> :m +Control.Arrow +Data.List +System.Random
>>> let groups = group $ map (fst . random . mkStdGen) [0 .. maxBound] :: [Bool]
>>> map (head &&& length) groups
[(True,53668),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53669),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53669),(False,53668),
(True,53668),(False,53668),(True,53669),(False,53668),(True,53668),(False,53669),
(True,53668),(False,53668),(True,53669),(False,53668),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53669),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53669),(False,53668),
(True,53668),(False,53668),(True,53669),(False,53668),(True,53668),(False,53669),
(True,53668),(False,53668),(True,53669),(False,53668),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53669),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53668),(False,53669),
(True,53668),(False,53668),(True,53669),(False,53668),(True,53668),(False,53669),
(True,53668),(False,53668),(True,53669),(False,53668),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53669),(False,53668),(True,53668),(False,53669),(True,53668),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53669),(False,53668),
(True,53668),(False,53669),(True,53668),(False,53668),(True,53668),(False,53669),
...
所以看来这些价值观中存在一种非常明确的模式。所有组的长度都是53668或53669,只要我想让它运行,它就会在True
和False
之间交替显示。
如果丢掉第一个值:
>>> let r :: StdGen -> (Bool, StdGen); r = random
>>> map (head &&& length) $ group $ map (fst . r . snd . r . mkStdGen) [1 .. maxBound]
[(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,1),(True,2),(False,1),(True,1),(False,2),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,1),
(False,2),(True,1),(False,1),(True,2),(False,1),(True,2),
(False,1),(True,1),(False,2),(True,1),(False,1),(True,2),
(False,1),(True,1),(False,2),(True,1),(False,1),(True,2),
...
这些在True
和False
之间交替的事实仅仅是因为group
以这种方式工作,所以不必担心。相反,请注意每组中的值的数量要小得多,而且难以预测,尽管我认为我仍然可以在其中看到一个模式(看看2s如何排列)。如果你要使用System.Random
,你应该确保在使用之前生成几个值,或者甚至更好,你可以在使用它之前生成一个随机数量的值。