gpt4 book ai didi

haskell - 如何使我的类型成为 Arbitrary 的实例?

转载 作者:行者123 更新时间:2023-11-28 20:03:52 26 4
gpt4 key购买 nike

我有以下数据和函数

data Foo = A | B deriving (Show)

foolist :: Maybe Foo -> [Foo]
foolist Nothing = [A]
foolist (Just x) = [x]

prop_foolist x = (length (foolist x)) == 1

当运行 quickCheck prop_foolist 时,ghc 告诉我 Foo 需要是 Arbitrary 的一个实例。

No instance for (Arbitrary Foo) arising from a use of  ‘quickCheck’
In the expression: quickCheck prop_foolist
In an equation for ‘it’: it = quickCheck prop_foolist

我试过 data Foo = A | B 派生 (Show, Arbitrary),但这导致

Can't make a derived instance of ‘Arbitrary Foo’:
‘Arbitrary’ is not a derivable class
Try enabling DeriveAnyClass
In the data declaration for ‘Foo’

但是,我不知道如何启用 DeriveAnyClass。我只是想通过我的简单功能使用快速检查! x 的可能值是 Nothing、Just A 和 Just B。当然这应该可以测试?

最佳答案

有两种合理的方法:

重用现有实例

如果有另一个看起来相似的实例,您可以使用它Gen 类型是 FunctorApplicative 甚至 Monad 的实例,因此您可以轻松地从其他的。这可能是编写 Arbitrary 实例最重要的通用技术。大多数复杂实例将由一个或多个更简单的实例构建。

boolToFoo :: Bool -> Foo
boolToFoo False = A
boolToFoo True = B

instance Arbitrary Foo where
arbitrary = boolToFoo <$> arbitrary

在这种情况下,Foo 不能以任何有意义的方式“收缩”为子部分,因此 shr​​ink 的默认简单实现可以正常工作。如果它是一个更有趣的类型,你可以使用一些类似的

  shrink = map boolToFoo . shrink . fooToBool

使用 Test.QuickCheck.Arbitrary 和/或 Test.QuickCheck.Gen

中可用的部分

在这种情况下,将各个部分放在一起非常容易:

import Test.QuickCheck.Arbitrary

data Foo = A | B
deriving (Show,Enum,Bounded)
instance Arbitrary Foo where
arbitrary = arbitraryBoundedEnum

如前所述,默认的 shr​​ink 实现在这种情况下就可以了。在递归类型的情况下,您可能想要添加

{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics (Generic)

然后根据您的类型和用途派生Generic

instance Arbitrary ... where
...
shrink = genericShrink

正如文档警告的那样,genericShrink 不遵守您可能希望强加的任何内部有效性条件,因此在某些情况下可能需要小心。


您询问了关于 DeriveAnyClass 的问题。如果你想要那个,你会添加

{-# LANGUAGE DeriveAnyClass #-}

到文件的顶部。但是你不想要那个。无论如何,你肯定不想在这里。它仅适用于具有基于泛型的完整默认值补充的类,通常使用 DefaultSignatures 扩展。在这种情况下,Arbitrary 类定义中没有 default arbitrary::Generic a => Gen a 行,arbitrary 是必需的。因此,一旦 QuickCheck 尝试调用其 arbitraryDeriveAnyClass 生成的 Arbitrary 实例将产生一个运行时错误方法。

关于haskell - 如何使我的类型成为 Arbitrary 的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35542734/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com