我想使用randomR在一个范围之间生成N个随机数。
我知道还有其他方法可以实现这一目标,例如使用randomRs
并在此代码中使用N,可以找到here:
diff_select :: Int -> Int -> StdGen -> [Int]
diff_select n m = take n . nub . randomRs (1, m)
但我希望使用 randomR
并使用State
monad。我不确定我在这个代码中犯了什么错误:
let fs = \s -> (randomR (0, 5) s, s)
let theState s = state (fs s)
let rep n ma = replicateM n (theState ma)
let res = runState (rep 3) (mkStdGen 4) -- Would like to use `get`
我该怎么做?
答案 0 :(得分:5)
使用State
monad生成随机数时,您希望状态值为生成器。在这种情况下,我们可以使用StdGen
:
type RandGen a = State StdGen a
然后你可以写出生成单个随机值的函数
getRandom :: Random a => RandGen a
getRandom = do
gen <- get
let (val, newGen) = random gen
put newGen
return val
现在,您可以使用此功能使用所有常用的Monad
函数生成多个随机数,例如sequence
,mapM
等。我们将让您实现此部分。最后,您所要做的就是执行代码:
> runState getRandom (mkStdGen 42) :: (Int, StdGen)
如果您想让它更容易,state
函数具有以下类型:
state :: MonadState s m => (s -> (a, s)) -> m a
random
的类型为
random :: (Random a, RandomGen g) => g -> (a, g)
注意s
和g
似乎排在这里的方式?您实际上可以通过
getRandom
getRandom :: Random a => RandGen a
getRandom = state random
所有艰苦的工作都是为你完成的。
答案 1 :(得分:0)
我想你想要:
let res = runState (rep 3) (mkStdGen 4)
你写的内容相当于:
runState (rep 3 (mkStdGen 4))
......这是不一样的。