如何覆盖包代码提供的 Haskell 类型类实例?
我有一些旧的 Haskell 代码,其中包括 QuickCheck 测试用例。较新版本的 QuickCheck(我刚刚升级到 2.4.0.1)包括 Arbitrary Word8
等的类型类实例。这些在旧版 2.0.x 版本的 Test.QuickCheck.Arbitrary 中不存在。
虽然在一般意义上很有用,但包提供的 Arbitrary Word8
生成器并不是我想要用于我的测试套件的生成器:
instance Arbitrary Word8 where
arbitrary = frequency [(2, oneof [return ctrlFrameDelim, return ctrlEscape, return ctrlXon, return ctrlXoff]),
(8, choose (0, 255))]
上面的代码会在编译时导致重复的实例声明错误。我可以取出这段代码并使用默认生成器,但我想知道解决此问题的正确方法。
我考虑过(但未测试)的一种可能的解决方案是使用 newtype
为 Word8
提供别名。这会导致整个源代码发生许多变化,所以我希望有一种更干净的方法。
编辑:正如下面的评论中提到的,接受的答案非常干净且易于实现:
newtype EncodedByte = EncodedByte Word8
instance Arbitrary EncodedByte where
arbitrary = liftM EncodedByte $ frequency [(2, elements [ctrlFrameDelim, ctrlEscape, ctrlXon, ctrlXoff]),
(8, choose (0, 255))]
I have some old Haskell code that includes QuickCheck test cases. Newer versions of QuickCheck (I've just upgraded to 2.4.0.1) include type class instances for Arbitrary Word8
and others. These did not exist in older 2.0.x versions of Test.QuickCheck.Arbitrary.
While useful in the general sense, the package-provided Arbitrary Word8
generator is not the one I want to use for my test suite:
instance Arbitrary Word8 where
arbitrary = frequency [(2, oneof [return ctrlFrameDelim, return ctrlEscape, return ctrlXon, return ctrlXoff]),
(8, choose (0, 255))]
The above code causes a duplicate instance declaration error at compile-time. I can take this code out and get by with the default generator but I'd like to know the proper way to solve this.
One possible solution I've considered (but not tested) is aliasing Word8
using newtype
. That would cause many changes throughout the source so I'm hoping there is a cleaner way.
EDIT: As mentioned in the comments below, the accepted answer was very clean and easy to implement:
newtype EncodedByte = EncodedByte Word8
instance Arbitrary EncodedByte where
arbitrary = liftM EncodedByte $ frequency [(2, elements [ctrlFrameDelim, ctrlEscape, ctrlXon, ctrlXoff]),
(8, choose (0, 255))]
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
newtype
别名是这里的标准解决方案。在大多数情况下(可能不包括您的情况),这没什么大不了的,因为 newtype 包装器只需要出现在您使用 Arbitrary 类型类的地方。例如,您可能在某个顶层:相反,您
可能想要的东西并不作为 GHC 扩展存在 - 您需要显式导入和导出实例。如果您有显式实例导入,这将允许:
但是会破坏当前通过实例隐式导入运行的许多代码:
A
newtype
alias is the standards solution here. In most cases, which might not include yours, this isn't a big deal because the newtype wrapper only needs to appear where you use the Arbitrary typeclass. For example, you might have at some top level:And instead you'd have
What you probably want doesn't exist as a GHC extension - you want explicit importing and exporting of instances. If you had explicit instance imports this would allow:
But break lots of code that currently works by implicit imports of instances: