QuickCheck: coarbitrary for Double and Float is broken.
coarbitrary definition for these types is incompatible with the way they are generated. First,
decodeFloat produces a pair
(Integer, Int), then the
Integer is manipulated to be positive and then coerced to an
fromInteger and passed to variant. Even 'simple' values of type
Float (as produced by
arbitrary) can have huge significands. In the case of Double, the resulting
Int can be negative due to truncation. This causes an exception when
variant uses '(!!)' with a negative index. Huge positive values are just as bad since they cause a space leak while evaluating
variant with a huge index (and tend not to terminate due to memory constraints). An obvious fix is to use the QuickCheck-2 approach.
To reproduce, import Test.QuickCheck and Text.Show.Functions, then run:
verboseCheck ((\f a -> f a == f a) :: (Float -> Int) -> Float -> Bool)
This should pass a few tests before finding a space leak.
verboseCheck ((\f a -> f a == f a) :: (Double -> Int) -> Double -> Bool)
This should also pass a few, then it may find a space leak, or it may error with:
*** Exception: Prelude.(!!): negative index
Note that QuickCheck-2 has no problems here.