
Hi all, Recently, I participated in a coding competition. As part of it, I had to write a program wherein I had to make my data-type an instance of Ord. An error in my implementation of compare resulted in me losing quite a bit of valuable time. As I wrote it, I had tested it out on the ghci and it seemed to work fine but I noticed that there was trouble when the List.sort started giving weird output. I then noticed that for certain instances (say t1,t2), both compare t1 t2 AND compare t2 t1 returned LT. Once I spotted it, it was easy enough to fix but I did lose an hour or so thinking something went wrong before I fed the list to the sort function. I was the only haskeller in the competition and I believe am among the first to finish a correct application (by a large margin, and) and I did manage to raise a bit of haskell-awareness, but if I had managed to spot the error earlier, the results would have been dazzling. Does any one here have any advice on dealing with such maladroitness on the part of the programmer, especially while creating instances to type-classes? Thanks and regards, Hemanth

Use QuickCheck.
2009/5/29 Hemanth Kapila
Hi all, Recently, I participated in a coding competition. As part of it, I had to write a program wherein I had to make my data-type an instance of Ord. An error in my implementation of compare resulted in me losing quite a bit of valuable time. As I wrote it, I had tested it out on the ghci and it seemed to work fine but I noticed that there was trouble when the List.sort started giving weird output. I then noticed that for certain instances (say t1,t2), both compare t1 t2 AND compare t2 t1 returned LT. Once I spotted it, it was easy enough to fix but I did lose an hour or so thinking something went wrong before I fed the list to the sort function. I was the only haskeller in the competition and I believe am among the first to finish a correct application (by a large margin, and) and I did manage to raise a bit of haskell-awareness, but if I had managed to spot the error earlier, the results would have been dazzling. Does any one here have any advice on dealing with such maladroitness on the part of the programmer, especially while creating instances to type-classes? Thanks and regards, Hemanth
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
-- Eugene Kirpichov Web IR developer, market.yandex.ru

Eugene Kirpichov wrote:
Use QuickCheck.
Also use SmallCheck or lazy SmallCheck. All of these are automatic tools that allow you to specify laws[1] and automatically generate values for testing the law. QuickCheck generates values randomly, which can be useful but is very often insufficient. Both versions of SmallCheck do exhaustive search of all values down to a bounded "depth" (lazy SmallCheck can often search deeper and faster). If you want to have decent assurances of correctness then use (lazy) SmallCheck. If you're dealing with a really branchy type which makes it prohibitive to search to any reasonable depth, then use QuickCheck in addition. Occasionally QuickCheck can be good for ferreting out really obscure corner cases, but SmallCheck is much better about guaranteeing you get all the basic cases. [1] e.g. prop_compare a b = compare a b == negateOrdering (compare b a) where negateOrdering LT = GT negateOrdering EQ = EQ negateOrdering GT = LT -- Live well, ~wren

Thanks Eugene and wren.
Serves me right, actually. The one chapter I skipped in RWH was the 11th one
called "Testing and Quality Assurance" thinking it is too boring.
On Fri, May 29, 2009 at 12:44 PM, wren ng thornton
Eugene Kirpichov wrote:
Use QuickCheck.
Also use SmallCheck or lazy SmallCheck.
All of these are automatic tools that allow you to specify laws[1] and automatically generate values for testing the law. QuickCheck generates values randomly, which can be useful but is very often insufficient. Both versions of SmallCheck do exhaustive search of all values down to a bounded "depth" (lazy SmallCheck can often search deeper and faster).
If you want to have decent assurances of correctness then use (lazy) SmallCheck. If you're dealing with a really branchy type which makes it prohibitive to search to any reasonable depth, then use QuickCheck in addition. Occasionally QuickCheck can be good for ferreting out really obscure corner cases, but SmallCheck is much better about guaranteeing you get all the basic cases.
[1] e.g.
prop_compare a b = compare a b == negateOrdering (compare b a) where negateOrdering LT = GT negateOrdering EQ = EQ negateOrdering GT = LT
-- Live well, ~wren
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Just pretend it was named "Test Driven Development" so it feels more
sexy while you read it :)
-- ryan
On Fri, May 29, 2009 at 5:05 AM, Hemanth Kapila
Thanks Eugene and wren. Serves me right, actually. The one chapter I skipped in RWH was the 11th one called "Testing and Quality Assurance" thinking it is too boring.
On Fri, May 29, 2009 at 12:44 PM, wren ng thornton
wrote: Eugene Kirpichov wrote:
Use QuickCheck.
Also use SmallCheck or lazy SmallCheck.
All of these are automatic tools that allow you to specify laws[1] and automatically generate values for testing the law. QuickCheck generates values randomly, which can be useful but is very often insufficient. Both versions of SmallCheck do exhaustive search of all values down to a bounded "depth" (lazy SmallCheck can often search deeper and faster).
If you want to have decent assurances of correctness then use (lazy) SmallCheck. If you're dealing with a really branchy type which makes it prohibitive to search to any reasonable depth, then use QuickCheck in addition. Occasionally QuickCheck can be good for ferreting out really obscure corner cases, but SmallCheck is much better about guaranteeing you get all the basic cases.
[1] e.g.
prop_compare a b = compare a b == negateOrdering (compare b a) where negateOrdering LT = GT negateOrdering EQ = EQ negateOrdering GT = LT
-- Live well, ~wren _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (4)
-
Eugene Kirpichov
-
Hemanth Kapila
-
Ryan Ingram
-
wren ng thornton