2016-02-18 277 views
0

我是哈斯克爾的新手,我一直試圖弄清楚這個問題一段時間了。我想使用randomRIO生成一個隨機大小的列表,並使用randomIO將該列表填充爲隨機數。我試圖通過創建一個函數,該函數在隨機randomRIO產生像這樣來解決這個問題:如何在Haskell中隨機生成一個隨機生成的數字列表

x <- randomRIO(1,5) 
let y = randList x [] 

本身的功能是這樣的:

randList :: Int -> IO [Int] -> IO [Int] 
randList 0 xs = return [xs] 
randList g xs = do 
      t <- randomIO 
      let a = t:randList (g-1) xs 
      return [a] 

我不知道怎麼樣在遞歸函數中處理monad IO,但這就是我想到的。任何幫助表示感謝,謝謝!

+0

注意,它在Haskell極力迴避擺在'IO'這樣的事情。最好接受一個明確的「RandomGen」參數(或者使用專門的monad來做這件事)。 – leftaroundabout

回答

4

您可以使用replicateM重複執行randomIO,每次生成一個新號碼。你叫randomRIO一次前場對列表的長度決定:

import Control.Monad (replicateM) 
import System.Random (randomIO, randomRIO) 

randList :: IO [Int] 
randList = do 
    len <- randomRIO (1,5) 
    replicateM len randomIO 

現在,你的定義本來就不是很離譜。一對夫婦的事情,但:

  • 既然你希望能夠調用randList x []randList第二個參數顯然是一個簡單的列表。不是某種IO操作。所以,你的類型應該是

    randList :: Int -> [Int] -> IO [Int] 
    
  • 在你的第一個模式匹配

    randList 0 xs = return [xs] 
    

    記住xs已經是一個列表。所以當你做return [xs]你會得到一個IO [[Int]],一個列表。你在這裏想要的是一個普通的return xs

  • 在你的第二個定義

    randList g xs = do 
        t <- randomIO 
        let a = t:randList (g-1) xs 
        return [a] 
    

    表達​​是沒有意義的。 :的右側必須是一個列表。 randList雖然不會產生列表,但會產生IO操作。你實際上想要做的是將randList(列表)的第二個參數作爲一個「累加器」來處理,這個累加器逐漸建立起來了。所以,你想生成一個號碼,將其添加到累加器,然後用g降低一個遞歸:

    randList g xs = do 
        t <- randomIO 
        randList (g-1) (t:xs) 
    
+0

這真的很有幫助,非常感謝!快速提問。有沒有像在正常列表中那樣用','來分隔數字? ***編輯:無視,我偶然得到了幾次的名單。再次感謝!! – Chris