使用System.Random中的mkStdGen生成随机布尔值

时间:2014-02-24 22:00:27

标签: haskell random

在以下程序中,为什么每一行都返回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

2 个答案:

答案 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,只要我想让它运行,它就会在TrueFalse之间交替显示。

如果丢掉第一个值:

>>> 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),
 ...

这些在TrueFalse之间交替的事实仅仅是因为group以这种方式工作,所以不必担心。相反,请注意每组中的值的数量要小得多,而且难以预测,尽管我认为我仍然可以在其中看到一个模式(看看2s如何排列)。如果你要使用System.Random,你应该确保在使用之前生成几个值,或者甚至更好,你可以在使用它之前生成一个随机数量的值。