5

经过一段时间令人沮丧的研究后,我正在写这篇文章,我希望这里有人可以启发我这个话题。

我想在 haskell 函数中生成一个简单的随机数,但是,如果没有各种重要的元素,例如 Monad、“do”中的分配、创建生成器等,这似乎是不可能的。

理想情况下,我正在寻找相当于 C 的“rand()”。但是经过大量搜索后,我非常确信没有这样的东西,因为语言是如何设计的。(如果有,请有人赐教)。由于这似乎不可行,我想找到一种方法来为我的特定问题获取随机数,以及如何获取随机数的一般解释。

prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = frequency [ 
    (1, return ([],[])),
    (2, do {
            xs1 <- orderedListEj13 ;
            xs2 <- orderedListEj13 ;
            return (xs1,xs2)
       }),
    (2, do {                
            xs2 <- orderedListEj13 ;
            return ((take RANDOMNUMBERHERE xs2),xs2)
       })
    ]

我正在尝试掌握 QuickCheck,但我无法使用随机数使其变得困难。我已经尝试过这样的事情(通过放置一个drawInt 0(长度xs2)而不是RANDOMNUMBERHERE)但我坚持认为需要一个Int并且该方法给我留下了一个IO Int,这似乎不可能转换为int依此

4

3 回答 3

7

由于 haskell 是一种函数式编程语言,函数是引用透明的,这意味着本质上只有函数的参数决定了它的结果。如果您能够从空中提取一个随机数,您可以想象这将如何导致问题。

我想你需要这样的东西:

prefixGenerator :: (Ord a, Arbitrary a) => Gen ([a],[a])
prefixGenerator = do
  randn <- choose (1,999) -- number in range 1-999
  frequency [ 
    (1, return ([],[])),
    (2, do {
            xs1 <- orderedListEj13 ;
            xs2 <- orderedListEj13 ;
            return (xs1,xs2)
       }),
    (2, do {                
            xs2 <- orderedListEj13 ;
            return ((take randn xs2),xs2)
       })
    ]

一般来说,在 haskell 中,您可以通过从 IO monad 中提取一些随机性,或者通过维护一个使用硬编码的整数种子初始化的 PRNG,或者从 IO 中提取来处理随机数生成(gspr 的评论非常好)。

阅读有关伪随机数生成器的工作原理可能会帮助您理解System.Random也可能会有所帮助(向下滚动到关于随机性的部分)。

于 2012-03-16T20:40:15.483 回答
4

你是对的,没有技巧就不可能生成不确定的随机数(我的意思是“伪随机数”)。Haskell 中的函数是函数,这意味着相同的输入将始终产生相同的输出。

好消息是您似乎不需要非确定性 PRNG。事实上,如果您的 QuickCheck 测试每次都使用相同的“随机”数字序列会更好,以使您的测试完全可重复。

您可以使用System.RandommkStdGen中的函数执行此操作。改编自Haskell 维基

import System.Random
import Data.List

randomInts :: Int -> [Int]
randomInts n = take n $ unfoldr (Just . random) (mkStdGen 4)

在这里,4您可能想通过公平的掷骰子来选择种子。

于 2012-03-16T20:39:49.063 回答
3

标准库为随机数生成提供了一个单子。monadic 的东西并不难学,但如果你想避免它,找到一个以伪随机方式next接受 an 的伪随机函数,Int然后Int创建并传递一个无限的随机数列表:

next :: Int -> Int
randoms :: [Int]
randoms = iterate next 73

然后,您可以在任何需要的地方传递这个随机数列表。

这是来自维基百科的线性同余next

next n = (1103515245 * n + 12345) `mod` 1073741824

以下是 73 之后的前 20 个伪随机数:

Prelude> take 20 $ iterate next 73
[73,25988430,339353199,182384508,910120965,1051209818,737424011,14815080,325218177,1034483750,267480167,394050068,4555453,647786674,916350979,980771712,491556281,584902142,110461279,160249772]
于 2012-03-17T01:39:03.860 回答