I’m trying to test this library with quickcheck. My core data type is an recursive ADT representing an ICU Message Format string.
I’ve derived a Generic instance for MessageFormatElement, and defined an Arbitrary instance using genericArbitrary from purescript-quickcheck.
Running my tests immediately blows the stack, presumably because the genericArbitrary definition isn’t stacksafe?
I see that Gen has a MonadRec instance, can I use that or purescript-safely to call genericArbitrary in a stacksafe way?
Am I better off manually writing the recursive part of arbitrary?
Is there anything else clearly wrong about what I’m attempting?
Any help appreciated.
genericArbitrary is probably unusable for recursive data structures. When writing a generator for a recursive structure you need to reduce the
size at each level of the structure so that it will stop generating at some point. Also the generator itself needs to be
sized to ensure that the
size state is observed .
You could take a look at the generator for
Json for an example of using size: https://github.com/purescript-contrib/purescript-argonaut-core/blob/master/src/Data/Argonaut/Gen.purs
Run into the same problem myself the other day. Substituting immediate recursive part with fix point solved it for me:
import Control.Lazy (fix)
import Data.NonEmpty ((:|))
import Test.QuickCheck.Arbitrary (class Arbitrary)
import Test.QuickCheck.Gen (oneOf)
data T a
= Leaf a
| V (T a)
| B (T a) (T a)
instance arbT :: Arbitrary a => Arbitrary (T a) where
arbitrary = fix $ \p -> oneOf (hd :| tl p)
hd = Leaf <$> arbitrary
tl p = [V <$> p, B <$> p <*> p]
Thanks, that’s a great example to work from!
fix from the
(also, TIL about
:| and the