tes*_*akt 5 haskell quickcheck
我正在阅读 Haskell Book,并且已经到了为newType Comp. 代码如下
instance Show (Comp a) where
show f = "Unicorns!!"
newtype Comp a =
Comp { unComp :: (a -> a) }
instance (Semigroup a) => S.Semigroup (Comp a) where
(Comp fx) <> (Comp fy) = Comp (fx . fy)
instance (CoArbitrary a, Arbitrary a) => Arbitrary (Comp a) where
arbitrary = do
f <- Test.QuickCheck.arbitrary
return (Comp f)
type CompAssoc = String -> Comp String -> Comp String -> Comp String -> Bool
compAssoc :: (S.Semigroup a, Eq a) => a -> Comp a -> Comp a -> Comp a -> Bool
compAssoc v a b c = (unComp (a <> (b <> c)) $ v) == (unComp ((a <> b) <> c) $ v)
Run Code Online (Sandbox Code Playgroud)
并测试
main :: IO ()
main = do
quickCheck (compAssoc :: CompAssoc)
Run Code Online (Sandbox Code Playgroud)
我的问题围绕着任意实例。它正在生成一个要传递给return (Comp f). 我明白(虽然不完全是为什么)这必须限于 CoArbitrary。可如果那东西传给return (Comp f)是CoArbitrary,又怎么会是Arbitrary?我想这些约束似乎都指的是函数的传递/返回类型和函数本身。我有点困惑。
这是一个初学者的、高水平的,在和之间的关系的底层细节解释中很可能是不正确的。ArbitraryCoArbitrary
这篇文章https://begriffs.com/posts/2017-01-14-design-use-quickcheck.html为您提供了更好的解释,但它使用了 Applicative 和 Functor,我还没有到达那里,因为我仍然在“The Haskell Book”的 SemiGroup 章节。
如果要从 生成函数a -> b,b则必须有 的实例Arbitrary。无论如何,我们都会生成随机的东西,所以我们Gen b像往常一样需要 a。但我们需要像普通函数一样改变它b,也就是说,如果我将不同的值传递给类似 的函数double,我会期望不同的响应。但是我们如何才能根据一些随机数来改变生成器a呢?b好吧,如果我们首先考虑生成随机数的方式,它与 有关numbers。也就是说,如果我想要一个随机数b(例如,Int),我只需生成一个随机数。十分简单。随机字符串?从随机数开始,将它们转换为 ASCII 字符。与您想要的任何其他数据类型相同,quickcheck 提供了很多Arbitrary可以做到这一点的实例。
好的,所以在基础上它是数字。我们可以通过获取其他数字然后乘/减/加/除来更改这些数字。或任何其他数学运算。但是我们如何获得另一个数字呢?这就是CoArbitrary进来的地方!如果我将一个类型标记为需要有一个实例CoArbitrary,那么我实际上是在说“我需要能够将您的类型减少到一个数字,以便我可以改变(添加/乘数/等)类型的生成器b。所以如果typea是一个字符串,例如,将该字符串减少为一个数字,将其传递给 gen for ,以便让type bGen for typeb对用于生成.mult/add/etcb
| 归档时间: |
|
| 查看次数: |
958 次 |
| 最近记录: |