Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
202 views
in Technique[技术] by (71.8m points)

quickcheck - How do you override Haskell type class instances provided by package code?

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))]
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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(..)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...