为什么这个列表包含多个不同的值?
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
并没有得到很多副本!它有一个生成器,并从那里开始完成所有工作。
我的代码如下所示:
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
并没有得到很多副本!它有一个生成器,并从那里开始完成所有工作。