Haskell 和随机数

标签 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]]的提示吗?

最佳答案

如何避免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 的完美示例——这里偏离了主题,但您接下来可能想研究一下。

关于Haskell 和随机数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2738581/

相关文章:

haskell - getZipList 是如何定义的?

haskell - 如何使用 Haskell pretty-print 分层缩进 "nest"

unit-testing - IO返回值测试

c++ - 使用 Boost 统一生成随机实数

Python-如何初始化随机函数

haskell - 对 "run"单子(monad)函数的直觉

flutter - 迁移到 Dart null safety : best practice for migrating ternary operator null checks? monadic 方法是否太不合常规?

Haskell - 限制数据参数

c - 关于随机整数生成的准则(C)

haskell - 在复合 StateT/Maybe monad 中,如何采取任何一种成功的可能性?