"read: no parse" with functionShow
Brent Yorgey
byorgey at seas.upenn.edu
Sun Jul 22 15:01:48 BST 2012
On Sun, Jul 22, 2012 at 02:01:49PM +0100, Nick Smallbone wrote:
> Hi Brent,
>
> You're right that functionShow internally generates a partial function
> on Strings - I hadn't thought much about that before. In itself, this
> isn't a problem: the function won't be applied to arbitrary strings,
> only to strings in the image of show, and QuickCheck should shrink
> away the partially-defined parts to leave a total function which can
> be printed. Indeed, you can generate a random function this way and
> try applying it to an Elt and see that it works.
>
> The problem is that Test.QuickCheck.Function's shrinking doesn't work
> on partial functions. The shrink function will return _|_ instead of a
> list of shrink candidates. Also, if you apply a showable function at
> an input where there's no matching case, we pick a default result;
> this default result is taken from the image of the function so can be
> _|_ if the function is partial. I've just pushed a patch that fixes
> all this: the shrinking works for partial functions, and we generate
> default results using arbitrary instead.
Hi Nick,
Thanks for the response. It works *more often* for me now (though it
seems to run two-three times slower). But I still sometimes get a
"read: no parse" error. Here is an excerpt from some output:
process/keepDelimsL match *** Failed! Falsifiable (after 22 tests and 3 shrinks):
Exception thrown by generator: 'Prelude.read: no parse'
NonEmpty {getNonEmpty = [Elt {unElt = 'c'},Elt {unElt = 'c'},Elt {unElt = 'b'},Elt {unElt = 'a'},Elt {unElt = 'a'},Elt {unElt = 'd'}]}
(Note that I expect a test failure; I deliberately introduced a bug.)
The property in question takes two arguments, Splitter Elt and
NonEmptyList Elt. A Splitter Elt has several fields, one of which is
a Delimiter Elt, which is defined by
newtype Delimiter a = Delimiter [a -> Bool]
and has an Arbitrary instance given by
instance (Arbitrary a, CoArbitrary a, Function a) => Arbitrary (Delimiter a) where
arbitrary = (Delimiter . map apply) <$> arbitrary
i.e. it generates an arbitrary list [Fun Elt Bool] using the Function
Elt instance, then converts it to an actual [Elt -> Bool] list.
Should this work? Am I doing something wrong here? I'm happy to send
you more info/a link to the repo if it would help.
-Brent
More information about the QuickCheck
mailing list