2012-03-16 59 views
5

我在寫了一段令人沮喪的研究之後寫了這篇文章,我希望這裏有人能夠啓發我關於這個話題。簡單的隨機數生成

我想產生一個Haskell函數的簡單隨機數,但很可惜,這似乎是不可能沒有的種種不平凡的元素,如單子,asignation在「做」的做,創造發電機等

理想情況下,我正在尋找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握手,但我無法使用隨機數字使它很難。我試過類似this(通過把一個drawInt 0(長度xs2)而不是RANDOMNUMBERHERE),但我堅持採取需要一個Int的事實,該方法留給我一個IO Int,這似乎不可能轉換爲Int根據this

+0

回想一下,Haskell是沒有副作用的語言。簡而言之,這意味着*不能是一個函數,例如C的'rand',每次調用它時都會給出一個僞隨機數。如果'rand'是一個純粹的Haskell函數給出了一個'Int',那麼它每次都給出相同的'Int' * *。但是,你可以做的是創建純函數,它將*隨機數發生器的狀態*作爲輸入,並返回下一個僞隨機數和發生器的新狀態。請參閱[System.Random](http://hackage.haskell.org/packages/archive/random/latest/doc/html/System-Random.html#v:random) – gspr 2012-03-16 20:36:26

+0

後續工作:「IO」單元,與您一樣當你想要管理一個全局的隨機狀態,或者例如用系統熵初始化你的發生器(這顯然需要與外界進行交互)時,纔會在'System.Random'模塊中使用。 – gspr 2012-03-16 20:39:43

回答

6

作爲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單子一些隨機性接近隨機數生成,或通過維護與某些整數種子初始化PRNG硬編碼,或從IO拉(gspr的評論是非常好的)。

閱讀關於僞隨機數生成器的工作原理可能會幫助您理解System.Randomthis也可能有所幫助(向下滾動到隨機性部分)。

+0

請注意,Gen是一個monad(除其他外)存儲一個隨機生成器狀態,以便您可以在Gen操作中的任何位置獲取隨機數。所以在quickcheck實例中沒有任何實際的隨機性問題。一般來說,初學者在其他情況下遇到困難,他們必須在算法中使用必要的框架來使用隨機性(並且在他們未能使用更好的解決方案時往往返回到IO)。 – Jedai 2012-03-16 23:53:35

+0

@傑代:謝謝,我沒有很好地解釋我的回答發生了什麼 – jberryman 2012-03-17 14:49:42

4

你是對的非確定性隨機(我的意思是「僞隨機」)數字生成是不可能的,沒有欺騙。 Haskell中的函數是純粹的這意味着相同的輸入將始終產生相同的輸出。

好消息是,你似乎不需要一個不確定的PRNG。事實上,如果您的QuickCheck測試每次都使用「隨機」數字序列的相同的以使您的測試完全重現,那將會更好。

您可以使用System.RandommkStdGen函數來執行此操作。從Haskell wiki改編:

import System.Random 
import Data.List 

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

這裏,4是,你可能希望通過一個fair dice roll選擇種子。

3

標準庫提供隨機數生成的monad。monadic的東西並不難學,但如果你想避免它,找到一個僞隨機函數next,以IntInt以僞隨機的方式,然後創建並傳遞一個無限的隨機數列表:

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] 
+0

不幸的是,標準庫實際上並沒有提供用於隨機數生成的monad。儘管如此,[MonadRandom](http://hackage.haskell.org/package/MonadRandom)庫確實如此。 – ehird 2012-03-17 06:34:10

+0

@ehird - 除非事情最近有變化'System.Random'帶有GHC,因此通過大多數測量使它成爲「標準」。 – 2012-03-17 08:21:10

+1

@stephentetley:'System.Random'沒有定義任何單子。事實上,[文檔](http://hackage.haskell.org/packages/archive/random/1.0.1.1/doc/html/System-Random.html)中唯一出現的「monad」出現在「 'IO' monad「。 – ehird 2012-03-17 08:49:04