1

Suppose, I have types like

data D = A | B String | C String
data TestIt m = TestIt {
   x :: m Int
 , y :: Int -> m D
}

and I am writing SmallCheck test, so I need Serial instance on TestIt:

instance Monad m => Serial m (TestIt m) where
  series = TestIt <$> (pure <$> series) <~> xxx

How to write this xxx? I understand that it maybe needs CoSerial like function, but 1) I am not sure 2) I don't know how to write it. When I see CoSerial documentation, I see that my CoSerial will have Int and not D in its definition:

instance (CoSerial m a) => CoSerial m (Int a) where
  coseries rs = ???

so I can not get idea of CoSerials and how to use them to make Serial for Int -> m D.

Also I want to have dependent serial for y field. I mean if x has sample 0 then serial of y should get 0 as argument. Is it possible?

RandomB
  • 3,367
  • 19
  • 30
  • `series = (cons0 $ const $ pure $ B "Xyz") \/ (cons0 $ const $ pure $ A) \/ (cons0 $ \n -> pure $ C $ someLogicOverDepArg n)` for `Serial m (Int -> m D)`. if it is needed variability on `B` then first component should be changed to be series of String. – RandomB Jul 09 '19 at 13:28
  • 1
    Please do not put code in the comments –  Jul 09 '19 at 15:31

1 Answers1

0

As example:

newtype MyFun m = MyFun (Int -> m D)

instance (Monad m, Monad n) => Serial m (MyFun n) where
  series = MyFun <$> (cons0 $ const $ pure $ A)
                 \/  (cons0 $ const $ pure $ B "XXX")
                 -- it shows how to depend on another field sample
                 \/  (cons0 $ \p -> pure $ C $ show p)

And y field of TestIt should be changed to MyFun m.

Then Serial instance of TestIt becomes trivial.

B is using with some constant string, C - with parameter, which can be got from sample of x field (this shows "dependency" between randomizing samples where one of them is a function):

testProperty "diffProcResult" $
   \(t::TestIt Identity) ->
     let (MyFun f) = y t
         yVal = f $ x t
     in ...
RandomB
  • 3,367
  • 19
  • 30