【发布时间】:2015-04-30 05:48:15
【问题描述】:
我的代码如下所示:
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和 10 个概率为 1/4)。
我能够通过猜测类型来使其工作,但我很困惑 --- evalState 不是在同一生成器的一堆不同副本上运行吗?为什么生成的列表不像[5, 5, 5, 5,...]?
【问题讨论】:
-
你可能会喜欢
randomRs。 -
@DanielWagner 这不会根据给定的分布对其进行加权。另外,我对这个问题的主要困惑是
Statemonad 的工作原理,而不是找到更好的方法来生成随机数。 -
我明白你的困惑是什么,并且正在写一个关于它的答案。评论是评论,不是回答。至于给定的分布——好吧,
randomR也没有。您可以在randomRs为您提供的无限列表上应用相同的转换,您可以对randomR为您提供的元素应用相同的转换。例如weightedRandomList (g, fs) = map (fs V.!) (randomRs (0, V.length fs - 1) g). -
@DanielWagner 知道了,谢谢!
标签: haskell random monads state-monad