如何覆盖包代码提供的Haskell类型类实例?

时间:2011-04-13 01:10:30

标签: haskell quickcheck

我有一些旧的Haskell代码,包括QuickCheck测试用例。较新版本的QuickCheck(我刚刚升级到2.4.0.1)包含Arbitrary Word8和其他版本的类型类实例。这些在Test.QuickCheck.Arbitrary的旧2.0.x版本中不存在。

虽然在一般意义上很有用,但是我提供的Arbitrary Word8生成器不是我想要用于测试套件的生成器:

instance Arbitrary Word8 where
  arbitrary = frequency [(2, oneof [return ctrlFrameDelim, return ctrlEscape, return ctrlXon, return ctrlXoff]),
                         (8, choose (0, 255))]

上述代码在编译时导致重复的实例声明错误。我可以使用默认生成器来获取此代码,但我想知道解决此问题的正确方法。

我考虑过(但未经过测试)的一种可能解决方案是使用Word8newtype进行别名处理。这将导致整个来源的许多变化,所以我希望有一个更清洁的方式。

编辑:正如下面的评论所述,接受的答案非常简洁,易于实施:

newtype EncodedByte = EncodedByte Word8

instance Arbitrary EncodedByte where
  arbitrary = liftM EncodedByte $ frequency [(2, elements [ctrlFrameDelim, ctrlEscape, ctrlXon, ctrlXoff]),
                                             (8, choose (0, 255))]

1 个答案:

答案 0 :(得分:10)

newtype别名是此处的标准解决方案。在大多数情况下,可能不包括你的,这不是什么大问题,因为newtype包装器只需要出现在你使用任意类型类的地方。例如,您可能处于某个顶级级别:

x <- arbitrary

相反,你有

newtype SomeNewType = SNT Word8
instance Arbitrary SomeNewType where ...
....
    SNT x <- arbitrary

您可能想要的不作为GHC扩展存在 - 您希望显式导入和导出实例。如果您有明确的实例导入,则允许:

import Test.QuickCheck hiding (Arbitrary(Word8))

但是打破了许多当前通过隐式导入实例工作的代码:

import Test.QuickCheck (quickCheck) -- note the implicit import of Arbitrary(..)