Как написать серийный экземпляр для этой функции? - PullRequest
0 голосов
/ 09 июля 2019

Предположим, у меня есть такие типы, как

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

и я пишу тест SmallCheck, поэтому мне нужно Serial экземпляр на TestIt:

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

Как написать это xxx? Я понимаю, что для этого может потребоваться функция CoSerial, но 1) я не уверен, 2) я не знаю, как это написать. Когда я вижу документацию CoSerial, я вижу, что у моего CoSerial будет Int, а не D в его определении:

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

поэтому я не могу понять CoSerial с и как их использовать, чтобы сделать Serial для Int -> m D.

Также я хочу иметь зависимый серийный номер для y поля . Я имею в виду, что если x имеет образец 0, тогда в качестве аргумента серийный номер y должен получить 0. Возможно ли это?

1 Ответ

0 голосов
/ 10 июля 2019

Как пример:

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)

И y поле TestIt должно быть изменено на MyFun m.

Тогда Serial экземпляр TestIt становится тривиальным.

B использует с некоторой константной строкой, C - с параметром, который можно получить из выборки поля x (это показывает «зависимость» между случайными выборками, где одна из них является функцией):

testProperty "diffProcResult" $
   \(t::TestIt Identity) ->
     let (MyFun f) = y t
         yVal = f $ x t
     in ...
...