我想使用randomR在一个范围之间生成N个随机数.
我知道有其他方法可以实现这一点,例如randomRs在此代码中使用和获取N,可在此处找到:
diff_select :: Int -> Int -> StdGen -> [Int]
diff_select n m = take n . nub . randomRs (1, m)
Run Code Online (Sandbox Code Playgroud)
但我想使用randomR和使用Statemonad.我不确定我在这个代码中犯了什么错误:
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`
Run Code Online (Sandbox Code Playgroud)
我怎样才能做到这一点?
使用Statemonad生成随机数时,您希望状态值为生成器.在这种情况下,我们可以使用StdGen:
type RandGen a = State StdGen a
Run Code Online (Sandbox Code Playgroud)
然后,您可以编写用于生成单个随机值的函数
getRandom :: Random a => RandGen a
getRandom = do
gen <- get
let (val, newGen) = random gen
put newGen
return val
Run Code Online (Sandbox Code Playgroud)
现在,你可以用它来生成使用所有常用的多个随机数Monad的功能,如sequence,mapM等我就让你实现这一部分.最后,您所要做的就是执行代码:
> runState getRandom (mkStdGen 42) :: (Int, StdGen)
Run Code Online (Sandbox Code Playgroud)
如果您想让它更容易,该state函数具有以下类型:
state :: MonadState s m => (s -> (a, s)) -> m a
Run Code Online (Sandbox Code Playgroud)
并random有类型
random :: (Random a, RandomGen g) => g -> (a, g)
Run Code Online (Sandbox Code Playgroud)
请注意这里s和如何g排队?实际上,你可以替换getRandom通过
getRandom :: Random a => RandGen a
getRandom = state random
Run Code Online (Sandbox Code Playgroud)
所有的辛勤工作都是为你完成的.
| 归档时间: |
|
| 查看次数: |
156 次 |
| 最近记录: |