Haskell 中的随机数列表
List with random numbers in Haskell
我想在 Haskell 中生成一个包含随机数的列表。我必须使用 import System.Random 库。我开始做类似的事情,但它不起作用。我必须创建一个包含 N 个位置的列表,所有这些位置都必须有随机数。谢谢!
System.Random library
import System.IO
x = randomRIO (1,6::Int)
test :: IO Int
test = randomRIO (1,6::Int)
您需要 运行 randomRIO
n 次。为此,您可以使用 replicate
。这将为您提供一元值列表,您可以使用 sequence
:
将其转换为一元值列表
test :: Int -> IO [Int]
test n = sequence $ replicate n $ randomRIO (1,6::Int)
虽然 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)
您应该注意以下几点:
- if
n == 0
函数将使用 return
将空列表包装成 IO
和 return this
- else 在
do
正文中,它将首先使用 randomRIO
生成一个随机数 r
- 接下来它将使用
randomList (n-1)
递归生成一个n-1
随机数元素列表并将其绑定到rs
- 最后它再次使用
return
将 r:rs
(一个 n
元素列表)包装到 IO
和 return 中
这是 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]
看起来很随意
remarks/exercise:
该函数对 n
的某些值有问题 - 你 能发现吗?如果是这样 - 你可以将函数更改为 total?
玩得开心
如果你仔细观察,你会发现你可以像这样拉出 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]
现在这已经完成了(稍微 different/better),你可以在 Control.Monad
中找到它作为 replicateM
- 通过这个导入函数简化为:
import System.Random (randomRIO)
import Control.Monad (replicateM)
randomList :: Int -> IO([Int])
randomList n = replicateM n $ randomRIO (1,6)
有趣的事实 internally 这与 JP 回答的完全一样;)
只使用一个生成器和无限列表
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
我想在 Haskell 中生成一个包含随机数的列表。我必须使用 import System.Random 库。我开始做类似的事情,但它不起作用。我必须创建一个包含 N 个位置的列表,所有这些位置都必须有随机数。谢谢!
System.Random library
import System.IO
x = randomRIO (1,6::Int)
test :: IO Int
test = randomRIO (1,6::Int)
您需要 运行 randomRIO
n 次。为此,您可以使用 replicate
。这将为您提供一元值列表,您可以使用 sequence
:
test :: Int -> IO [Int]
test n = sequence $ replicate n $ randomRIO (1,6::Int)
虽然 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)
您应该注意以下几点:
- if
n == 0
函数将使用return
将空列表包装成IO
和 return this - else 在
do
正文中,它将首先使用randomRIO
生成一个随机数 - 接下来它将使用
randomList (n-1)
递归生成一个n-1
随机数元素列表并将其绑定到rs
- 最后它再次使用
return
将r:rs
(一个n
元素列表)包装到IO
和 return 中
r
这是 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]
看起来很随意
remarks/exercise:
该函数对 n
的某些值有问题 - 你 能发现吗?如果是这样 - 你可以将函数更改为 total?
玩得开心
如果你仔细观察,你会发现你可以像这样拉出 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]
现在这已经完成了(稍微 different/better),你可以在 Control.Monad
中找到它作为 replicateM
- 通过这个导入函数简化为:
import System.Random (randomRIO)
import Control.Monad (replicateM)
randomList :: Int -> IO([Int])
randomList n = replicateM n $ randomRIO (1,6)
有趣的事实 internally 这与 JP 回答的完全一样;)
只使用一个生成器和无限列表
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