是否可以统一产生一个随机的无限斑点?
我尝试构建一个 RNG,它在 3 个项目中均匀随机选择。因为,常见的习惯用法(例如 C 的 rand() % 3
)很容易出现模偏差,因此不统一。
根据可接受性的概念,我的想法是统一生成随机无限位串,并通过函数映射它。以下陈述应满足:
函数对于几乎所有输入都停止(这个“几乎所有”是测度论中一个明确定义的概念)
这 3 个项目的诱导概率分布是均匀的
因此,我的代码草图是在 Haskell 中:
import Data.Word
import System.Random
infixr 5 :!
data InfWord64 = Word64 :! InfWord64
execute :: (InfWord64 -> a) -> IO a
execute f = do
let getWordString = do
headWord <- randomIO
tailWords <- getWordString
pure (headWord :! tailWords)
fmap f getWordString
randomOrderingMap :: InfWord64 -> Ordering
randomOrderingMap (headWord :! tailWords)
| headWord < 0x5555555555555555 = LT
| 0x5555555555555555 < headWord && headWord < 0xAAAAAAAAAAAAAAAA = EQ
| 0xAAAAAAAAAAAAAAAA < headWord = GT
| otherwise = randomOrderingMap tailWords
randomOrdering :: IO Ordering
randomOrdering = execute randomOrderingMap
但它不能正常工作。似乎 execute
对于每个输入都会陷入无限循环。看起来单子语句 headWord <- randomIO
将被无限执行。
我需要某种惰性IO
,但它不存在是有充分理由的。惰性 ST RealWorld
是一种替代方案,但当 random
包仅支持严格的 ST
时,我看不到任何使用它的方法。那么解决方法是什么呢?
I tried to build an RNG that uniformly randomly chooses amongst 3 items. Because, the common idiom (something like C's rand() % 3
) is prone to modulo bias, and thus not uniform.
As per the notion of admissibility, my idea was to uniformly generate a random infinite bitstring, and map it through a function. The following statements shall satisfy:
The function halts for almost all inputs (This "almost all" is a well-defined notion in measure theory)
The induced probability distribution over the 3 items is uniform
As such, my sketch of code was, in Haskell:
import Data.Word
import System.Random
infixr 5 :!
data InfWord64 = Word64 :! InfWord64
execute :: (InfWord64 -> a) -> IO a
execute f = do
let getWordString = do
headWord <- randomIO
tailWords <- getWordString
pure (headWord :! tailWords)
fmap f getWordString
randomOrderingMap :: InfWord64 -> Ordering
randomOrderingMap (headWord :! tailWords)
| headWord < 0x5555555555555555 = LT
| 0x5555555555555555 < headWord && headWord < 0xAAAAAAAAAAAAAAAA = EQ
| 0xAAAAAAAAAAAAAAAA < headWord = GT
| otherwise = randomOrderingMap tailWords
randomOrdering :: IO Ordering
randomOrdering = execute randomOrderingMap
But it doesn't work properly. It seems execute
would fall into an infinite loop for every input. It seems the monadic statement headWord <- randomIO
would be executed infinitely.
I would need some kind of lazy IO
, but it doesn't exist for good reasons. Lazy ST RealWorld
would be an alternative, but I don't see any way to use this when the random
package supports only strict ST
. So what's the workaround?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
system.random
生成懒惰的无限伪随机流的首选方法是使用Randoms
。例如:这里,
infwords
是一个普通的,懒惰的,无限的haskell列表pseudorandomword64
s。The preferred way of generating a lazy infinite pseudorandom stream using
System.Random
is to userandoms
. For example:Here,
infwords
is a normal, lazy, infinite Haskell list of pseudorandomWord64
s.在您的代码中,似乎您想通过
getWordString
与随机数的懒惰 list(或流)一起工作,然后在纯函数RandomordorderingMap中使用它
。并不是一种不合理的方法,而是创建这样的懒惰列表,实际上将下一个呼叫的执行延迟到getWordString
需要懒惰的IO。因此,如果将递归调用替换为
getWordString
unsafeinterleaveio getWordString
(请参阅 docs ),然后它应该起作用。尝试将
putstrln
语句添加到getWordString
以观察该功能中的IO操作何时执行。这不一定是解决此问题的最直接或惯用方法,通常不适合不安全的功能,而是学习经验,这很有用。
In your code, it seems you want to work with a lazy list (or stream) of random numbers via
getWordString
, and then consume it in the pure functionrandomOrderingMap
. Not an unreasonable approach to play around with, but creating such a lazy list, and actually deferring the execution of the next call togetWordString
, requires lazy IO.So if you replace the recursive call to
getWordString
withunsafeInterleaveIO getWordString
(see docs), then it should work.Try adding a
putStrLn
statement togetWordString
to observe when exactly the IO action in this function is executed.This is not necessarily the most direct or idiomatic way of solving this problem, and usually one does not reach for unsafe function, but as a learning experience this is useful.