【问题标题】:How to create a random list in haskell如何在haskell中创建一个随机列表
【发布时间】:2020-09-28 01:53:39
【问题描述】:

我是 haskell 的新手,遇到了这个问题:正如标题所说,我正在尝试使用随机数创建一个给定长度的列表,范围在一些 x 和 y 之间。例如,如果 x=0 且 y=10,则列表将类似于:[0,4,3,8,0,2]。我更喜欢用列表理解来做,没有任何 IO。我看过一些关于类似主题的帖子,但到目前为止没有一个对我有帮助。

【问题讨论】:

  • 因为你想要的不可能。值是确定性的。没有 io 意味着没有随机。
  • 虽然@ThomasM.DuBuisson 是正确的,但您仍然可以创建看似随机的伪随机列表,但是对于任何给定种子,您将获得相同的随机列表。

标签: list haskell random list-comprehension


【解决方案1】:

使用random包中的System.Random,这正是randomRs的函数:

randomRs :: (Random a, RandomGen g) => (a, a) -> g -> [a]

它接受一个值范围和一个生成器,并返回该范围内随机值的惰性列表。您可以使用 mkStdGen 从固定种子制作生成器:

mkStdGen :: Int -> StdGen

例如,这里有一个种子(在我的机器上,使用我的特定版本 random)巧合地产生了您提供的示例值:

> take 6 $ randomRs (0, 10) $ mkStdGen 15915
[0,4,3,8,0,2]

如果您希望程序在每次调用时产生不同的随机值,您必须使用 IO 为随机数生成器播种当前时间。为此,您可以改用newStdGen

newStdGen :: IO StdGen

一个完整的例子:

import System.Random (newStdGen, randomRs)

main :: IO ()
main = do
  gen <- newStdGen
  print $ randomList 6 0 10 gen

randomList
  :: (Random a, RandomGen g)
  => Int -> a -> a -> g -> [a]
randomList len lo hi gen = take len $ randomRs (lo, hi) gen

【讨论】:

    【解决方案2】:

    Jon Purdy 的出色回答使用库函数 randomRs 解决了这个问题。这很好用。

    但是,存在随机数生成器的最终状态丢失的缺点。在一般情况下,您可能对随机数有其他需求,因此您需要该最终状态,将其用作这些其他需求的初始状态。

    最终状态的丢失与randomRs 提供无限随机数供应这一事实有关,因此没有适当的最终状态。但是您的问题文本提到了“给定长度的列表”。所以没有必要使用randomRs。相反,您可以使用返回单个随机数的函数getRandomR 作为基本构建块。

    最常用的方法是使用MonadRandom 类和runRand 评估函数。这给出了这种源代码:

    import  System.Random
    import  System.Random.TF -- Threefish algorithm
    import  Control.Monad.Random
    
    
    -- monadic action to get *count* random numbers between xmin and xmax
    someRandomNumbers :: MonadRandom mr => Int -> Int -> Int -> mr [Int]
    someRandomNumbers xmin xmax count =
        sequence (replicate count (getRandomR (xmin, xmax)))
    
    
    main = do
        let count    = 6
            seed     = 377708  -- adjusted to get exactly [0,4,3,8,0,2]  :-)
            randGen0 = mkTFGen seed
            action   = someRandomNumbers 0 10 count
    
            (xs, randGen1) = runRand action randGen0  -- get final state too
        putStrLn $ "random xs = " ++ (show xs)
    
    

    程序输出:

    random xs = [0,4,3,8,0,2]
    

    注意 1: 我使用 Threefish random number generator 代替标准生成器,因为已知它有 better statistical properties

    注意2:完全不涉及IO,除了最终打印结果的时候。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-19
      • 1970-01-01
      • 2018-07-15
      • 2011-10-20
      • 2012-05-06
      相关资源
      最近更新 更多