哈斯克尔的共同任命

时间:2017-12-16 19:49:46

标签: 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)

并使用

进行测试
main :: IO ()
main = do
    quickCheck (compAssoc :: CompAssoc)

我的问题围绕着任意实例。它正在生成一个传递给return (Comp f)的函数。我理解(尽管不完全是为什么)这必须是CoArbitrary的范围。但如果传递给return (Comp f)的内容是CoArbitrary,那么它又如何Arbitrary?我想似乎这些约束都指的是函数的传递/返回类型和函数本身。我有点困惑。

1 个答案:

答案 0 :(得分:1)

这是初学者,高级,很可能在底层细节中不正确Arbitrary和{{之间关系的解释1}}。

文章https://begriffs.com/posts/2017-01-14-design-use-quickcheck.html为您提供了更好的解释,但它使用了Applicative和Functor,但我还没有到达那里,因为我仍然在#34; The Haskell Book&#34;

如果要从CoArbitrary生成函数,a -> b必须具有b的实例。无论如何我们都会生成随机内容,因此我们需要像往常一样Arbitrary。但是我们需要改变这个Gen b就像普通函数一样,也就是说,如果我将一个不同的值传递给像b这样的函数,I&# 39; d期待不同的回应。但是,我们怎样才能根据某些随机double改变生成器?好吧,如果我们考虑一下我们首先生成随机a的方式,它就与b有关。即如果我想要一个随机numbers(比如说​​Int),我只需要生成一个随机数。十分简单。随机字符串?从随机数开始,将它们转换为ASCII字符。与您想要的任何其他数据类型相同,并且quickcheck提供了许多{I}个实例。

好的,所以在基地是数字。 我们可以通过获得一些其他数字来改变这些数字,然后比如乘以/减去/加/除。或任何其他数学运算。但是我们如何获得其他数字呢? b进来的地方!如果我将某个类型标记为需要拥有Arbitrary的实例,实际上我会说&#34;我需要能够将您的类型减少到一个数字,以便我可以变化(add / mult / etc)类型CoArbitrary的生成器。因此,如果类型CoArbitrary是一个字符串,例如,将该字符串减少为一个数字,将其传递给b的gen,以便让类型为a的Gen执行{ {1}}对用于生成type b数字进行操作。