我有一些旧的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))]
上述代码在编译时导致重复的实例声明错误。我可以使用默认生成器来获取此代码,但我想知道解决此问题的正确方法。
我考虑过(但未经过测试)的一种可能解决方案是使用Word8
对newtype
进行别名处理。这将导致整个来源的许多变化,所以我希望有一个更清洁的方式。
编辑:正如下面的评论所述,接受的答案非常简洁,易于实施:
newtype EncodedByte = EncodedByte Word8
instance Arbitrary EncodedByte where
arbitrary = liftM EncodedByte $ frequency [(2, elements [ctrlFrameDelim, ctrlEscape, ctrlXon, ctrlXoff]),
(8, choose (0, 255))]
答案 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(..)