2

I am trying to write tests for arbitrary Repa Arrays in Haskell. For some reason, the following snippet:

import Test.QuickCheck
import Test.QuickCheck.Monadic
import Data.Array.Repa (Array, DIM2)

prop_id :: Array U DIM2 Double -> Property
prop_id array = monadicIO $ array `R.equalsP` array >>= assert

throws this exception:

*** Failed! (after 1 test): 
Exception:
Test.QuickCheck.resize: negative size
CallStack (from HasCallStack):
    error, called at ./Test/QuickCheck/Gen.hs:82:22 in QuickCheck-2.9.2-Jyj4gc4JxkEIgGFLAsGhs9:Test.QuickCheck.Gen
Exception thrown while printing test case:
Test.QuickCheck.resize: negative size
CallStack (from HasCallStack):
    error, called at ./Test/QuickCheck/Gen.hs:82:22 in QuickCheck-2.9.2-Jyj4gc4JxkEIgGFLAsGhs9:Test.QuickCheck.Gen

I'm not sure how to interpret this information. Thanks for your help.

duplode
  • 33,731
  • 7
  • 79
  • 150
ethanabrooks
  • 747
  • 8
  • 19

1 Answers1

2

This is a bug in repa's Arbitrary instance. arbitrary crashes at size 0. You can fix the generator used by your property in the mean time:

quickCheck $ forAll (scale (+1) arbitrary) prop_id
Li-yao Xia
  • 31,896
  • 2
  • 33
  • 56
  • Thank you for the response! I would not have figured that out on my own. Is there a way to do this with `quickCheckAll` i.e.: `runTests = $quickCheckAll $ forAll (scale (+1) arbitrary)`? – ethanabrooks Apr 30 '17 at 02:48
  • Unfortunately not. There isn't such a fine-grained way to tweak the generators used by QuickCheck. To avoid having to mangle all of your generators, you have to override repa's `Arbitrary` instances. Their root module imports the `Arbitrary` instances and it seems hard to avoid since it's the one exporting the `Array` type. However, properties are monomorphic, so you can take advantage of the fact that existing `Arbitrary` instances are parametric, and implement a `Arbitrary (Array U sh Double)` for example in your test module with `{-# OVERLAPPING #-}`, fixing repa's generic instance. – Li-yao Xia Apr 30 '17 at 03:05
  • Will do! Thanks. – ethanabrooks Apr 30 '17 at 03:24
  • First, I should say that your first suggestion worked. However, the following code did not (threw same error as before): `instance {-# OVERLAPPING #-} T.Arbitrary (Array U DIM1 Double) where arbitrary = T.scale (+1) $ T.arbitrary >>= A.arbitraryUShaped` – ethanabrooks Apr 30 '17 at 18:02
  • Your property above is using `DIM2`, so this instance is not being selected. – Li-yao Xia Apr 30 '17 at 20:59