Haskell的纯伪随机生成器,有很好的API吗?

Haskell的纯伪随机生成器,有很好的API吗?,haskell,random,Haskell,Random,对于纯伪随机发生器(均匀双工),推荐的Haskell软件包是什么 首先我对一个方便的API感兴趣,速度也不错 可能是mwc random?该标准具有纯界面。我建议将其包装成状态g(对于您正在使用的任何生成器g),以避免线程化状态;该函数可以轻松地将next等函数转换为有状态操作: next :: (RandomGen g) => g -> (Int, g) state :: (s -> (a, s)) -> State s a state next :: (RandomG

对于纯伪随机发生器(均匀双工),推荐的Haskell软件包是什么

首先我对一个方便的API感兴趣,速度也不错

可能是mwc random?

该标准具有纯界面。我建议将其包装成
状态g
(对于您正在使用的任何生成器g),以避免线程化状态;该函数可以轻松地将
next
等函数转换为有状态操作:

next :: (RandomGen g) => g -> (Int, g)
state :: (s -> (a, s)) -> State s a
state next :: (RandomGen g) => State g Int
该软件包基于
状态g
接口,带有发电机功能的预写包装;我认为它相当受欢迎

请注意,您仍然可以使用此纯接口运行操作。莫纳德兰多姆已经为这一目标做出了努力

我认为您可以编写一个(孤立的)实例来使用mwc random来处理这些问题。

我喜欢这个包。例如,您可以这样使用它从种子值生成无限个随机双精度延迟流:

import Data.Word (Word64)
import Data.List (unfoldr)
import System.Random.Mersenne.Pure64

randomStream :: (PureMT -> (a, PureMT)) -> PureMT -> [a]
randomStream rndstep g = unfoldr (Just . rndstep) g

toStream :: Word64 -> [Double]
toStream seed = randomStream randomDouble $ pureMT seed

main = print . take 10 $ toStream 42
使用系统随机(随机)

您可以使用内置的
randoms
函数获得类似的输出,该函数更短、更通用(感谢ehird指出这一点):

使其成为MonadRandom的一个实例

在阅读了《蒙纳德兰多姆》(MonadRandom)之后,我开始好奇如何让《蒙纳德兰多姆》(MonadRandom)成为它的一个实例。开箱即用,它不起作用,因为
PureMT
没有实例化
RandomGen
split
函数。使其工作的一种方法是将
PureMT
包装在
newtype
中,并为
RandomGen
typeclass编写一个自定义
split
实例,其中存在一个默认的
MonadRandom
实例

import Control.Monad.Random
import System.Random.Mersenne.Pure64

getTenRandomDoubles :: Rand MyPureMT [Double]
getTenRandomDoubles = getRandoms >>= return . take 10

main = print $ evalRand getTenRandomDoubles g
  where g = MyPureMT $ pureMT 42


newtype MyPureMT = MyPureMT { unMyPureMT :: PureMT }
myPureMT = MyPureMT . pureMT

instance RandomGen MyPureMT where
  next  = nextMyPureMT
  split = splitMyPureMT

splitMyPureMT :: MyPureMT -> (MyPureMT, MyPureMT)
splitMyPureMT (MyPureMT g) = (myPureMT s, myPureMT s') where
  (s',g'') = randomWord64 g'
  (s ,g' ) = randomWord64 g

nextMyPureMT (MyPureMT g) = (s, MyPureMT g') where
  (s, g') = randomInt g

一个特别好的包,它有一个纯接口,也适用于加密应用程序,同时保持高性能

它提供了两个接口:一个是使用System.Random中的类型类的确定性纯接口,另一个是使用Crypto API包中的类型类的强IO接口


作为旁注:我通常更喜欢mersenne random软件包而不是mwc random软件包。他们使用原始的Mersenne Twister算法,在我的基准测试中,其性能比mwc random高出一个大的因数。

@ehird这里有什么无IO的随机性源可以保持它的纯净?ECC?@JFritsch:记住,纯净并不意味着没有IO。纯函数必须在给定相同参数的情况下始终返回相同的结果。唯一的“随机性来源”是生成器或种子(
g
,在类型签名中)。@JFritsch:没有PRNG为每个数字咨询外部来源;你只是从那里得到种子。您可以从种子创建类型为
StdGen
(一个
RandomGen
的实例)的值,IO中有一个全局生成器,可能是从外部源种子生成的。@ehird对于P RNGs,您肯定是对的。否则“否”有点强:D。在web2.0世界中,良好的随机性是一个问题,IO在其中扮演着重要角色。你可以为任何
RandomGen
(其中
PureMT
就是一个例子)使用
randoms::(RandomGen g,Random a)=>g->[a]
@ehird哦,不知道
Random
!更新了我的答案在
mersenne-random-pure64
之上还构建了
monad mersenne random
。它有一个很好的特性,它允许在恒定的内存空间中运行一元迭代(请参见此问题:)。@sastanin感谢您为我指出相关的问题,
monad mersenne random
,给了我一些新的见解!
import Control.Monad.Random
import System.Random.Mersenne.Pure64

getTenRandomDoubles :: Rand MyPureMT [Double]
getTenRandomDoubles = getRandoms >>= return . take 10

main = print $ evalRand getTenRandomDoubles g
  where g = MyPureMT $ pureMT 42


newtype MyPureMT = MyPureMT { unMyPureMT :: PureMT }
myPureMT = MyPureMT . pureMT

instance RandomGen MyPureMT where
  next  = nextMyPureMT
  split = splitMyPureMT

splitMyPureMT :: MyPureMT -> (MyPureMT, MyPureMT)
splitMyPureMT (MyPureMT g) = (myPureMT s, myPureMT s') where
  (s',g'') = randomWord64 g'
  (s ,g' ) = randomWord64 g

nextMyPureMT (MyPureMT g) = (s, MyPureMT g') where
  (s, g') = randomInt g