Random Monad是否在replicateM迭代之间独立?

时间:2014-11-04 12:46:51

标签: haskell random random-sample

我在纸牌游戏中做了一些假设检验。

为此,我实施了游戏和玩游戏的AI。对于测试,我必须在我的牌组中所有可能的卡片安排的空间上进行抽样(牌组有24张牌,所以有24张不同的牌组初始状态)。然而,抽样应该是独立的,因为(a)在洗牌之后,每个初始安排应该具有概率(1/24!)和(b)如果i和i'在两次洗牌之后的两个初始安排是安排我和然后安排i'最初的安排应该是(1/24!)x(1/24!)。[注1]

所以,如果 d 是我的牌组,那么 shuffleDeck 就是我洗牌的功能。我相信随机monad的构建方式是概率((suffleDeck d)== i)= 1/24!

但我的问题是:当与函数replicateM交互时,此函数是否独立?换句话说,以下是真的吗?

P((replicateM 2(shuffleDeck d))== [i,i'])= P((suffleDeck d)== i)* P((suffleDeck d)== i&#39 ;)

其中P(x = X)是x为X的概率。

我用于shuffle的代码如下:

import System.Random

shuffleDeck d = do
         seed <- newStdGen 
         return $ shuffle seed d

shuffle :: StdGen -> [Card] -> [Card]
shuffle g [] = [] 
shuffle g d  = c : shuffle g' d'
        where (c, g') = oneRandomCard g d 
              d' = d\\[c]

oneRandomCard :: StdGen -> [Card] -> (Card, StdGen)
oneRandomCard g d =((last $ take n d), g1 )
              where (n,g1) = randomR (1, length d) g

我看到第一眼看来这个问题似乎微不足道,但考虑到haskell对待随机性的方式,我觉得值得提问。

[1]注意:分配不需要像我说的那样统一。它只需要是一个已知的分布,所以我可以掌握测试的力量。但在这种情况下它应该是统一的。

[2]注意:如注释中所述,该函数仅使用System.Random而不是Control.Monad.Random。

2 个答案:

答案 0 :(得分:5)

由于您的示例仅使用replicateM中的IO,因此问题实际上略显不完整。 replicateM 2 (shuffleDeck d)的类型为IO [[Card]]。它永远不会等同[[Card]]类型的东西。但是,虽然这个技术问题在使用Haskell时非常重要,但我会忽略它来回答我认为是你的基本问题。

据我所知,您的基本问题是以下两段代码之间是否存在差异:

decks d = replicateM 2 (shuffleDeck d)

decks d = do
    d1 <- shuffleDeck d
    d2 <- shuffleDeck d
    return [d1, d2]

如果这两者之间存在差异,则会破坏相关类型的Monad实例。 monad法则与replicateM的定义相结合,要求这些表达式具有相同的结果。

答案 1 :(得分:2)

首先,很好的问题。并回答你的问题,是的,你的等式确实存在。在您的代码中,您显式线程化了生成器而不是使用MonadRandom。当你使用MonadRandom时,你应该会发现你的方程式不仅仅能保持,而且两种不同的双重混乱方法实际上应该会给你相同的改组。 (这假设您以确定的方式而不是使用IO为种子生成种子)。均等推理和反馈透明度是强大的。如果我能进一步澄清,请告诉我。