haskell生成随机序列并通过生成器

时间:2016-02-10 16:30:12

标签: haskell random

我想在传递randomGenerator mkStdGen

的同时创建随机序列

我想出了以下内容,这似乎有效,但我想知道是否有更好/更合适的方法吗?

genRandomSeq :: (RandomGen g, Random a) => Int -> (a,a) -> g -> ([a], g)
genRandomSeq n rng g =
  foldr (\_ (acc,g') -> (\(a,g'') -> (a:acc, g'')) (randomR rng g')) ([],g) [0..n]


-- which is basically the same as
genRandomSeq 0 rng g collected = (collected, g)
genRandomSeq n rng g collected =
  let (a,g') = randomR rng g in
  genRandomSeq (n - 1) rng g' (a : collected)


(xs,g)  = genRandomSeq 5 ('a','z') (mkStdGen 10)
(ys,g') = genRandomSeq 5 ('a','z') g

zs = "my nice string: " ++ xs ++ ys :: String

正在使用

*Main> genRandomSeq 5 ('a','z') (mkStdGen 10)
("rrsvfx",1928412403 1780294415)
*Main> zs
"my nice string: rrsvfxyaygon"

1 个答案:

答案 0 :(得分:1)

我发现明确传递种子很笨重,令人烦恼并导致可组合性差。我最喜欢的方法是使用自定义monad进行随机数生成。 The MonadRandom library是他们所有人的祖父,我明白,但也有random-fu这更有特色,但开始时有点困难。

使用MonadRandom和类似工具,您的函数可以这样编写(未经过测试,但应该是正确的):

import Control.Monad (replicateM)
import Control.Monad.Random

genRandomSeq :: Random a => Int -> (a,a) -> Rand g [a]
getRandomSeq n range = replicateM n (getRandomR range)

-- Your function is this, but in practice I might not bother writing it
-- out as its own definition—basically, I'd work in the `Rand` monad as 
-- much as possible and only `runRand` where I really need to.
runIt :: (RandomGen g, Random a) => Int -> (a,a) -> g -> ([a], g)
runIt n range g = runRand (getRandomSeq n range) g

如果你还没有研究State monad,那么这对你来说是个好点。 Rand monad只是一个专门的状态monad,具有一些实用函数,可以更容易地使用随机生成。

练习:编写您自己的Rand类型版本,FunctorApplicativeMonad个实例以及{{1}操作。