简体   繁体   English

在Haskell中列出随机数

[英]List with random numbers in Haskell

I want to generate a list with random numbers in Haskell. 我想在Haskell中生成一个包含随机数的列表。 I have to use the import System.Random library. 我必须使用import System.Random库。 I started doing something like that but it doesn't work. 我开始做类似的事情,但它不起作用。 I have to create a list with N positions, and all these positions must have random numbers. 我必须创建一个包含N个位置的列表,并且所有这些位置必须具有随机数。 Thanks! 谢谢!

System.Random library
import System.IO

x = randomRIO (1,6::Int) 

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

You need to run randomRIO n times. 你需要运行randomRIO n次。 For this you can use replicate . 为此,您可以使用replicate This will give you a list of monadic values, that you can transform into a monadic list of values with sequence : 这将为您提供一个monadic值列表,您可以将其转换为带sequence的monadic值列表:

test :: Int -> IO [Int]
test n = sequence $ replicate n $ randomRIO (1,6::Int)

While JP Moresmau solution is certainly preferable, you might be interested in a more transparent solution that shines some light on the do notation and recursive functions using IO : 虽然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) 

you should note the following: 你应该注意以下几点:

  • if n == 0 the function will use return to wrap the empty list into IO and return this 如果n == 0该函数将使用return将空列表包装到IO并返回此值
  • else inside the do body it will first generate a random number r using randomRIO do主体内部,它将首先使用randomRIO生成随机数r
  • next it will recursively generate a n-1 element list of random numbers using randomList (n-1) and bind it to rs 接下来,它将使用randomList (n-1)以递归方式生成随机数的n-1元素列表,并将其绑定到rs
  • finally it uses return again to wrap r:rs (a n element list) into IO and return it 最后它再次使用returnr:rs (一个n元素列表)包装到IO并返回它

here is an example in GHCi : 这是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]

seems random enough 似乎随机

remarks/exercise: 备注/运动:

the function has a problem with certain values of n - can you spot it? 该函数有一定的n值问题 - 你能发现它吗? And if so - can you change the function to be total ? 如果是这样的话 - 你可以将功能改为总数吗?

having some fun 有一些乐趣

If you look closely you see that you can pull out randomRIO (1,6) :: IO Int there like this: 如果你仔细观察,你会看到你可以像这样拉出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) 

which of course you would have to use like this: 当然你必须使用这样的:

λ> mList 10 $ randomRIO (1,6)
[2,2,2,5,5,1,3,6,6,1]

now this has been done before (in a slightly different/better) way and you can find it as replicateM in Control.Monad - with this import the function simplifies to: 现在这已经完成了(以稍微不同/更好)的方式,你可以在Control.Monad找到它作为replicateM - 通过这个导入,该函数简化为:

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

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

fun fact internally this is implemented exactly as what JP answered ;) 内部 有趣的事实,这与JP回答的完全相同;)

Using only one generator and infinite list 仅使用一个生成器和无限列表

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM