QuickCheck Gen不是monad

时间:2014-06-30 00:50:50

标签: haskell quickcheck

我偶尔会看到有人说QuickCheck中的Gen类型不遵守monad法则,尽管我没有看到很多解释。现在,QuickCheck 2.7的Test.QuickCheck.Gen.Unsafe模块说Gen只是“道德上”的monad,但简短的解释让我摸不着头脑。你能否一步一步地说明Gen如何打破monad法律?

1 个答案:

答案 0 :(得分:25)

如果你想证明某些东西是单子,那么你必须证明它符合monad法则。这是一个

m >>= return = m

Gen的文档指的是该法律中(=)的实际含义。 Gen值是函数,因此很难比较它们的相等性。相反,我们可能会内联(>>=)return的定义,并通过等式推理证明法律适用

m       = m       >>= return
m       = m       >>= (\a -> MkGen (\_ _ -> a))
MkGen m = MkGen m >>= (\a -> MkGen (\_ _ -> a))
MkGen m = MkGen (\r n ->
                    let (r1,r2)  = split r
                        MkGen m' = (\a -> MkGen (\_ _ -> a)) (m r1 n)
                    in m' r2 n
                )
MkGen m = MkGen (\r n ->
                    let (r1,r2)  = split r
                        MkGen m' = MkGen (\_ _ -> m r1 n)
                    in m' r2 n
                )
MkGen m = MkGen (\r n ->
                    let (r1,r2)  = split r
                    in (\_ _ -> m r1 n) r2 n
                )
MkGen m = MkGen (\r n ->
                    let (r1,r2)  = split r
                    in m r1 n
                )
MkGen m = MkGen (\r -> m (fst $ split r))

所以,最终,除非fst . split == idwhich is doesn't,否则monad法律似乎无法成立。不应该。

但从道德上讲,fst (split r)r相同吗?好吧,只要我们操作好像我们对种子价值一无所知,是的,fst . split在道德上等同于idGen - as-a-function产生的实际值会有所不同,但值的分布是不变的。

这就是文档所指的内容。我们在monad法则中的平等并不等同,而是通过将Gen a视为a的值的概率分布而仅在“道德上”。