Haskell和随机数

时间:2010-04-29 15:27:26

标签: haskell random monads

几天来我一直在捣乱Haskell并且偶然发现了一个问题。

我需要一个返回随机整数列表的方法(Rand [[Int]])。

所以,我定义了一个类型:type Rand a = StdGen -> (a, StdGen)。 我能以某种方式生成Rand IO IntegerRand [IO Integer](returnR lst) :: StdGen -> ([IO Integer], StdGen))。有关如何制作Rand [[Int]]的任何提示?

4 个答案:

答案 0 :(得分:20)

如何避免IO取决于它首先被引入的原因。虽然伪随机数生成器本质上是面向状态的,但没有理由IO需要参与。

我会猜测并说您正在使用newStdGengetStdGen来获取您的初始PRNG。如果是这种情况,那么就无法完全逃脱IO。您可以使用mkStdGen直接为PRNG播种,请记住,相同的种子将导致相同的“随机”数字序列。

更有可能的是,你要做的是在IO内获得PRNG,然后将其作为参数传递给纯函数。当然,整个事情仍然会被包裹在IO中,但中间计算不需要它。这是一个快速举例说明:

import System.Random

type Rand a = StdGen -> (a, StdGen)

getPRNG = do
    rng <- newStdGen
    let x = usePRNG rng
    print x

usePRNG :: StdGen -> [[Int]]
usePRNG rng = let (x, rng') = randomInts 5 rng
                  (y, _) = randomInts 10 rng'
              in [x, y]

randomInts :: Int -> Rand [Int]
randomInts 0 rng = ([], rng)
randomInts n rng = let (x, rng') = next rng
                       (xs, rng'') = randomInts (n - 1) rng'
                   in (x:xs, rng'')

您可能会注意到,使用PRNG的代码由于不断地来回传递当前值而变得相当丑陋。它也可能容易出错,因为很容易意外地重用旧值。如上所述,使用相同的PRNG值将给出相同的数字序列,这通常不是您想要的。这两个问题都是一个完美的例子,说明使用State monad是有意义的 - 这是在这里脱离主题,但你可能想要接下来查看它。

答案 1 :(得分:11)

您正在Hackage上重新创建MonadRandom。如果这不仅仅是一个实验,看看你是否可以这样做,你可能想要使用该库。

答案 2 :(得分:6)

如果你想获得一个无限Integer列表,你会遇到问题,因为你不会得到StdGen值。你想在这里做的是split StdGen首先,再将一半传递出来,然后“用完”另一半来生成无限的整数列表。像这样:

infiniteRandomInts :: Rand [Int]
infiniteRandomInts g = (ints, g2) where
    (g1,g2) = split g
    ints = randoms g1

但是,如果你重复这种方法来获得Integer s的无限矩阵(你似乎想要使用Rand [[Int]]),你可能遇到统计性的问题:我不知道StdGen如何处理重复的split ting。也许RandomGen的另一个实现可能会更好,或者您可以尝试使用某种对角线步行将[Int]转换为[[Int]]

答案 3 :(得分:3)

使用monadic表示法,您应该能够编写类似

的内容
randomList gen = do
    randomLength <- yourRandomInteger
    loop gen (randomLength + 1)
 where
    loop gen 1 = gen
    loop gen n = do { x <- gen; xs <- loop gen (n - 1); return (x:xs) }

用这个

randomInts :: Rand [Int]
randomInts = randomList yourRandomInteger

randomLists :: Rand [[Int]]
randomLists = randomList randomInts

关于monadic计算本身,请看this article。请注意,随机生成器是纯粹的,您不应该只为此目的使用任何IO