Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果没有范围内的IO,如何在Haskell中生成随机数?_Haskell_Random - Fatal编程技术网

如果没有范围内的IO,如何在Haskell中生成随机数?

如果没有范围内的IO,如何在Haskell中生成随机数?,haskell,random,Haskell,Random,我想生成一个范围内的随机数,类型签名为Int->Int。我读过多篇其他文章,但没有一篇建议返回类型Int。我在代码中使用了System.IO.Unsafe,但不建议这样做。这是我的密码: import System.IO.Unsafe -- random number generator rng :: Int -> Int rng upper = unsafePerformIO $ randomRIO (0,upper-1) 有人对如何在Haskell中生成范围内的随机整数有什么建议

我想生成一个范围内的随机数,类型签名为
Int->Int
。我读过多篇其他文章,但没有一篇建议返回类型
Int
。我在代码中使用了
System.IO.Unsafe
,但不建议这样做。这是我的密码:

import System.IO.Unsafe

-- random number generator
rng :: Int -> Int
rng upper = unsafePerformIO $ randomRIO (0,upper-1) 
有人对如何在Haskell中生成范围内的随机整数有什么建议吗

编辑:可能无法更改
IO Int->Int
,因此我将代码转换为

-- random number generator
rng :: Int -> IO Int
rng upper = randomRIO (0,upper-1) 
我之所以需要一个rng,是因为我想获取列表长度范围内的随机数,以获取列表元素的索引

列表!!rng(长度列表)
但我发现错误
无法将预期的类型“Int”与预期的实际类型“IO Int”匹配


它不是重复的,因为1。我希望值在2的范围内。我的rng不返回相同的值。我是哈斯克尔的新手,我不知道如何操纵单子。感谢您的帮助。

Haskell不是为了在不使用
IO的情况下生成随机数而构建的

您的示例,
list!!rng(长度列表)
,不起作用,因为
rng
返回
IO Int
需要一个
Int

下面是一个使用
rng
函数从列表中获取随机元素的函数:

-- Will crash on empty list
randomElementFromList :: [a] -> IO a
randomElementFromList list = do
  r <- rng (length list)
  return $ list !! r
--将在空列表上崩溃
randomElementFromList::[a]->IO a
randomElementFromList=do
rI本着的精神,这里有一个没有任何IO的“解决方案”:

rng :: Int -> Int
rng upper
 | upper<=4   = upper
 | otherwise  = 4
…或者,您可以显式地将更新的状态与结果一起传递

rng'' :: Int -> RandStV -> (RandStV, Int)
rng'' upper x =
   let x' = ((x * 1103515245) + 12345) `mod` 0x7fffffff
   in (x', x `mod` upper)
…或者它可以通过专用的方式传递,这只是编写更新变量传递的另一种方式:

type RandStM = State RandStV

rng''' :: Int -> RandStM Int
rng''' upper = do
   x <- get
   let x' = ((x * 1103515245) + 12345) `mod` 0x7fffffff
   put x'
   return $ x `mod` upper
类型RandStM=状态RandStV
rng“”::Int->RandStM Int
rng''上限=do

你不能理智地把它变成
Int->Int
。你能得到的最接近并且仍然表现得理智的是
Int->StdGen->(StdGen,Int)
;此类型可以使用
randomR
而不是
randomRIO
实现。可能重复
rng x=fst$randomR(0,x-1)$makeStdGen$length“https://xkcd.com/221“
:p您不需要涉及IO,但由于Haskell引用的透明性,您不能拥有
Int->Int
类型签名。”。没有理由将此指定为
[Int]
randomElementFromList::[a]->IO a
当然还有模式
do{x
type RandStM = State RandStV

rng''' :: Int -> RandStM Int
rng''' upper = do
   x <- get
   let x' = ((x * 1103515245) + 12345) `mod` 0x7fffffff
   put x'
   return $ x `mod` upper