你如何覆盖包代码提供的Haskell类型类实例? [英] How do you override Haskell type class instances provided by package code?

查看:172
本文介绍了你如何覆盖包代码提供的Haskell类型类实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

 实例任意Word8其中
arbitrary = frequency [(2,one of [return ctrlFrameDelim,return ctrlEscape,return ctrlXon,return ctrlXoff]),
(8,choose(0,255))]

上面的代码在编译时会导致重复的实例声明错误。我可以把这段代码拿出来,用默认的生成器来处理,但我想知道解决这个问题的正确方法。



我考虑过的一种可能的解决方案但未经测试)使用 newtype 来别名 Word8 。这将导致整个源代码的许多变化,所以我希望有一个更清洁的方式。编辑:正如在下面的评论中提到的,接受的答案是非常干净的,易于实现:

  newtype EncodedByte = EncodedByte Word8 

实例Arbitrary EncodedByte其中
任意= liftM EncodedByte $ frequency [(2,元素[ctrlFrameDelim,ctrlEscape,ctrlXon,ctrlXoff]),
(8,选择(0,255))]


解决方案

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

  x < - 任意

相反,您会有

  newtype SomeNewType = SNT Word8 
实例Arbitrary SomeNewType其中...
....
SNT x < - 任意

您可能想要的内容不作为GHC扩展名存在 - 您希望显式导入和导出实例。如果你有显式的实例导入,这将允许:
$ b $ pre $ import Test.QuickCheck hiding(Arbitrary(Word8))

但是打破了大量目前通过隐式导入实例工作的代码:

  import Test.QuickCheck(quickCheck) - 注意隐式导入Arbitrary(..)


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))]

解决方案

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:

x <- arbitrary

And instead you'd have

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

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:

import Test.QuickCheck hiding (Arbitrary(Word8))

But break lots of code that currently works by implicit imports of instances:

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

这篇关于你如何覆盖包代码提供的Haskell类型类实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆