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

Why does this list contain more than one distinct value?

我的代码如下所示:

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 以 3/4 的概率吐出 5,以 1/4 的概率吐出 10)。

我能够通过猜测类型来让它工作,但我很困惑 --- 不是 evalState 得到 运行 一堆不同的副本同一台发电机?为什么生成的列表看起来不像 [5, 5, 5, 5,...]

自从您在 nextWeightedRandom 中调用 put 后,每次迭代都会更新状态。所以每次调用 randomR ... g 时,它都会使用上一次迭代的生成器输出。

事实上,问题本身,"isn't evalState getting run over a bunch different copies of the same generator" 是一个非常有趣的问题,因为 evalState 并没有得到很多副本!它有一个生成器,并从那里开始完成所有工作。