为什么此列表包含多个不同的值?

时间:2015-04-30 05:48:16

标签: haskell random monads state-monad

我的代码如下:

import qualified Data.Vector as V
import System.Random
import Control.Monad.State.Lazy
nextWeightedRandom :: State (StdGen, V.Vector Int) Int
nextWeightedRandom = do
  (g, fs) <- get
  let (i, g') = randomR (0, V.length fs - 1) g
  put (g', fs)
  return (fs V.! i)

weightedRandomList :: (StdGen, V.Vector Int) -> [Int]
weightedRandomList = evalState $ mapM (\_ -> nextWeightedRandom) [1..]

QuickCheck确认来自weightedRandomList的值不同,并且具有我希望的大致分布(Vector Int看起来像[5, 5, 5, 10],因此nextWeightedRandom吐出5的概率为3/4,10概率为1/4)。

我能够通过猜测我的方式来实现它的类型,但我很困惑---不是evalState运行在同一个生成器的一堆不同副本上?为什么生成的列表看起来不像[5, 5, 5, 5,...]

1 个答案:

答案 0 :(得分:4)

由于您在put中调用nextWeightedRandom,因此每次迭代都会更新状态。因此,每次调用randomR ... g时,它都会使用上一次迭代的生成器输出。

事实上,这个问题本身并没有evalState在同一个发电机的一堆不同副本上运行&#34;是一个非常有趣的,因为evalState没有交给任何东西的许多副本!它被赋予一个单一的生成器,并从那里开始所有的工作。