Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.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
Haskell 哈斯克尔随机数_Haskell - Fatal编程技术网

Haskell 哈斯克尔随机数

Haskell 哈斯克尔随机数,haskell,Haskell,我试图在Haskell中生成一个随机数样本 import System.Random getSample n = take n $ randoms g where g = newStdGen 但是我似乎没有正确地使用newStdGen。我遗漏了什么?首先,您可能不想使用newStdGen。最大的问题是,每次运行程序时都会得到不同的种子,因此没有可复制的结果。在我看来,mkStdGen是一个更好的选择,因为它需要你给它一粒种子。这意味着您每次都将获得相同的(伪)随机数序列。如果需要不同

我试图在Haskell中生成一个随机数样本

import System.Random

getSample n = take n $ randoms g where
    g = newStdGen

但是我似乎没有正确地使用
newStdGen
。我遗漏了什么?

首先,您可能不想使用
newStdGen
。最大的问题是,每次运行程序时都会得到不同的种子,因此没有可复制的结果。在我看来,
mkStdGen
是一个更好的选择,因为它需要你给它一粒种子。这意味着您每次都将获得相同的(伪)随机数序列。如果需要不同的序列,只需更改种子即可

newStdGen
的第二个问题是,由于它不纯净,您最终会进入IO单子,这可能有点不方便

sample :: Int -> IO [Int]
sample n = do
  gen <- newStdGen
  return $ take n $ randoms gen
我们的主要功能是现在

main :: IO ()
main = do
  let seed1 = mkStdGen 123456
      (xs,seed2) = sample 10 seed1
      s = sum xs
      (ys,seed3) = sample 10 seed2
      t = sum ys
  print s
  print t
我知道仅仅使用随机数似乎需要做很多工作,但其优点是值得的。我们可以用一个种子产生我们所有的随机性,这保证了结果可以被复制

当然,这是Haskell,我们可以利用Monad来摆脱所有手动线程的种子值。这是一种稍微高级一点的方法,但值得学习,因为单子在Haskell代码中无处不在

我们需要这些进口:

import System.Random
import Control.Monad
import Control.Applicative
然后我们将创建一个新类型,它表示将一个种子转换为一个值和下一个种子的操作

newtype Rand a = Rand { runRand :: StdGen -> (a,StdGen) }
我们需要
Functor
Applicative
实例,否则GHC会抱怨,但我们可以避免在本例中实现它们

instance Functor Rand
instance Applicative Rand
现在来看Monad实例。这就是魔法发生的地方。
>=
函数(称为bind)是我们指定如何在计算中遍历种子值的地方

instance Monad Rand where
  return x = Rand ( \seed -> (x,seed) )
  ra >>= f = Rand ( \s1 -> let (a,s2) = runRand ra s1
                           in  runRand (f a) s2 )

newRand :: Rand Int
newRand = Rand ( \seed -> random seed )
现在我们的
示例
函数非常简单!我们可以利用
Control.Monad
中的
replicItem
,它重复给定的操作并将结果累积到列表中。所有关于种子价值观的有趣的事情都是在幕后处理的

sample :: Int -> Rand [Int]
sample n = replicateM n newRand

main :: IO ()
main = do
  let seed1 = mkStdGen 124567
      (xs,seed2) = runRand (sample 10) seed1
      s = sum xs
  print s
如果需要多次生成随机值,我们甚至可以留在
Rand
monad中

main :: IO ()
main = do
  let seed1 = mkStdGen 124567
      (xs,seed2) = flip runRand seed1 $ do
        x <- newRand
        bs <- sample 5
        cs <- sample 10
        return $ x : (bs ++ cs)
      s = sum xs
  print s
main::IO()
main=do
设seed1=mkStdGen 124567
(xs,seed2)=翻转runRand seed1$do

谢谢!有一件事让我困惑:我从一个纯函数开始,它需要一个随机数列表作为输入(本质上是做一个
sum$map someFunction randomNumbers
)。然而,上面生成的随机数是一元的(这是一个词吗?),似乎我不能把它们仅仅放在我的纯函数中。在哈斯克尔,解决这个问题的正确方法是什么?我认为没有一种“正确”的方法。我已经在上面概述了我个人的偏好。你可能对解决眼前问题的“最便捷”方式更感兴趣。在这种情况下,请尝试使用
fmap sum$map someFunction randomNumbers
,或使用
mkStdGen 123456
代替
newStdGen
。(123456可以是任意整数)
instance Monad Rand where
  return x = Rand ( \seed -> (x,seed) )
  ra >>= f = Rand ( \s1 -> let (a,s2) = runRand ra s1
                           in  runRand (f a) s2 )

newRand :: Rand Int
newRand = Rand ( \seed -> random seed )
sample :: Int -> Rand [Int]
sample n = replicateM n newRand

main :: IO ()
main = do
  let seed1 = mkStdGen 124567
      (xs,seed2) = runRand (sample 10) seed1
      s = sum xs
  print s
main :: IO ()
main = do
  let seed1 = mkStdGen 124567
      (xs,seed2) = flip runRand seed1 $ do
        x <- newRand
        bs <- sample 5
        cs <- sample 10
        return $ x : (bs ++ cs)
      s = sum xs
  print s