我想写一个这样的函数:
myFnc :: Gen -> ([Int], Gen)
使用MWC Random。一般的想法是使用预定义的种子创建第一个Gen
,然后以绝对纯粹的方式生成Int
s和新Gen
s的无限序列。
所以我开始尝试将种子Gen
表示为Int
。文档说我可以使用initialize
函数来完成它。很好,让我们看看,它需要Word32
s的向量,所以尝试这个至少得到一个随机Int
:
import System.Random.MWC
import Data.Vector.Generic
rere :: IO ()
rere =
do gen <- initialize (singleton 42)
x <- uniform gen :: Int
print x
但它没有编译。错误:
Couldn't match expected type ‘Int’ with actual type ‘m0 a0’
In a stmt of a 'do' block: x <- uniform gen :: Int
In the expression:
do { gen <- initialize (singleton 42);
x <- uniform gen :: Int;
print x }
我查看了文档,但它似乎与我非常简单的初始愿望相距甚远......
似乎我也不能使用uniform
,因为它在monad中返回值,所以我真的不知道如何从所有这些东西中创建一个简单的Int
s列表。< / p>
例如,以下是我要实现的内容,但System.Random
:
import System.Random
mkStdGen 5 -- first: that's how to create generator from given Int
myFnc :: StdGen -> ([Int], StdGen) -- second: desired function
myFnc g = (randoms g, fst . split $ g)
这很有效。
答案 0 :(得分:1)
我implemented a sample of this on FP Haskell Center。实施的核心是:
randoms :: (Variate a, PrimMonad m) => Gen (PrimState m) -> m [a]
randoms gen =
loop
where
loop = return $ unsafeInlinePrim $ do
x <- uniform gen
xs <- loop
return $! x : xs
请注意,它的类型签名与您要求的不同。特别是,没有&#34; split&#34;在mwc-random中。另外,在mwc-random中获取随机数本身就是一个可变的动作,所以我们需要生活在一些PrimMonad
中以及使用不安全的内联。这可能是安全的,假设您从未使用过其他地方提供的Gen
。
但是,我认为您应该尝试重构您的程序以接受mwc-random的可变性质,或者切换到mersenne-random-pure64之类的纯随机数生成器。
答案 1 :(得分:0)
在System.Random.MWC中,&#34;制服&#34;返回一个类型&#34; m a&#34;但是你试图将它限制在Int。这就是你的错误所抱怨的。
把
x :: Int
在上一行。