2014-02-18 55 views
2

我寫了一個函數從[-10,10]中隨機獲得一對。Haskell:隨機數

import System.Random 


main = 
    do { 
     s <- randomNumber 
     ; b <- randomNumber 
     ; print (head s,head b)} 
randomNumber :: IO [Int] 
randomNumber = sequence $ replicate 1 $ randomRIO (-10,10) 

現在我想要一個像[(1,2),(2,3),(2,3)]這樣的列表,所有的數字都來自randomNumber。我怎樣才能做到這一點?我不知道如何實現這一點。

我試圖使用狀態來獲得隨機,但不知何故,我不能在我的電腦上使用狀態。 我這樣做:

import System.Random 
import Control.Monad.State 
randomSt :: (RandomGen g, Random a) => State g a 
randomSt = State random 

但是,當我編譯它,它表明:在範圍:數據構造「國家」

回答

5

所以,如果你想要的是一個功能

然後我們可以做類似

randomList :: IO [Int] 
    randomList = randomRs (-10, 10) `fmap` newStdGen 
    randomPairs = ??? randomList randomList 

其中???需要兩個IO [Int]並將它們「拉」到一起形成IO [(Int, Int)]。我們現在來hoogle和查詢功能[a] -> [a] -> [(a, a]),我們發現一個函數zip :: [a] -> [b] -> [(a, b)]我們現在只需要「提升」 zipIO單子跨越0​​列表與它的工作,所以我們結束了

randomPairs = liftM2 zip randomList randomList 

或如果我們想成爲真正看中的,我們可以改用applicatives與

import Control.Applicative 

    randomPairs = zip <$> randomList <*> randomList 

最終但是從你的randomNumber功能可按來看,你真的只是想一個對。這個想法非常相似。相反,生成一個列表,我們僅僅產生一個隨機數與randomRIO (-10, 10)和提升(,) :: a -> b -> (a, b)導致

randomPair = (,) <$> randomRIO (-10, 10) <*> randomRIO (-10, 10) 

最後,State數據構造就走了前一陣子,因爲MTL從具有獨立StateStateT類型使得移動State一個類型的同義詞。現在,你需要使用小寫state :: (s -> (s, a)) -> State s a

爲了澄清,我的最終代碼是

import System.Random 
import Control.Monad 

randomList :: IO [Int] 
randomList = randomRs (-10, 10) `fmap` newStdGen 

pairs :: IO [(Int, Int)] 
pairs = liftM2 zip randomList randomList 

somePairs n = take n `fmap` pairs 

main = somePairs 10 >>= print 
+0

正如你所看到的,我有進口Control.Monad.State,那麼我仍然無法使用它。 – Xie

+0

@Xie我的錯誤,我已經更新了我的答案 – jozefg

+0

嗨,你的代碼通過了編譯,但是當我運行它時,它顯示內存不足。看起來像randomList有什麼問題嗎? – Xie