在Haskell中生成随机数列表

5

我希望在Haskell中生成一个包含随机数的列表。我需要使用导入System.Random库。我尝试着做一些事情,但它并不起作用。我需要创建一个有N个位置的列表,而且所有这些位置都必须有随机数。谢谢!

System.Random library
import System.IO

x = randomRIO (1,6::Int) 

test :: IO Int
test = randomRIO (1,6::Int)

1
请更详细地描述目前哪些部分有问题。 - Ali Beadle
3个回答

16
你需要运行randomRIO n次。你可以使用replicate来实现。这将给你一个单子值列表,你可以用sequence把它转换成一个值的单子列表:
test :: Int -> IO [Int]
test n = sequence $ replicate n $ randomRIO (1,6::Int)

1
然后我们可以以点为中心编写它 test = ($ randomRIO (1,6::Int)) . replicateM - madnight

11

虽然JP Moresmau的解决方案肯定更可取,但您可能对更透明的解决方案感兴趣,该解决方案使用IO来说明do符号和递归函数:

import System.Random (randomRIO)

randomList :: Int -> IO([Int])
randomList 0 = return []
randomList n = do
  r  <- randomRIO (1,6)
  rs <- randomList (n-1)
  return (r:rs) 

请注意以下内容:

  • 如果n == 0,该函数将使用return将空列表包装成IO并返回它
  • 否则,在do体内,它将首先使用randomRIO生成一个随机数r
  • 接下来,它将递归生成一个由n-1个随机数元素组成的列表,并将其绑定到rs
  • 最后,它再次使用returnr:rs(一个n元素列表)包装成IO并返回它

这是在GHCi中的示例:

λ> randomList 10
[2,4,4,5,2,2,2,5,6,2]

λ> randomList 10
[2,4,4,2,5,2,6,3,4,1]

看起来足够随机

备注/练习:

该函数在某些n的值上存在问题 - 你能发现吗?如果可以,你能将函数改为完美吗?

玩一下

如果你仔细观察,就会发现可以像这样提取出randomRIO (1,6) :: IO Int

mList :: Int -> IO a -> IO([a])
mList 0 gen = return []
mList n gen = do
  r  <- gen
  rs <- mList(n-1) gen
  return (r:rs) 

当然,您需要像这样使用它:
λ> mList 10 $ randomRIO (1,6)
[2,2,2,5,5,1,3,6,6,1]

现在这个功能已经被实现了(以稍微不同/更好的方式),你可以在Control.Monad中找到它的实现,通过引入该模块,该函数变得更加简单:

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

randomList :: Int -> IO([Int])
randomList n = replicateM n $ randomRIO (1,6)

趣闻 内部实现与JP回答的完全相同


3

只使用一个生成器和无限列表

import Data.List
import System.Random

randomList :: (Int, Int) -> IO [Int]
randomList interval =
  newStdGen >>= return . unfoldr (Just . randomR interval)

main :: IO ()
main = do
  ls <- randomList (1, 6)
  putStrLn $ show $ take 4 ls

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接