Summing Testing

I want to test an applicative instance on a user type:

module SumMonad where

  import Test.QuickCheck (Arbitrary, arbitrary, elements, Gen)
  import Test.QuickCheck.Checkers (quickBatch, eq, (=-=), EqProp)
  import Test.QuickCheck.Classes (applicative)

  data Sum a b =
      First a
    | Second b
    deriving (Eq, Show)

  instance Functor (Sum a) where
    fmap _ (First x) = First x
    fmap f (Second y) = Second (f y)

  instance Applicative (Sum a) where
    pure = Second
    First x <*> _ = First x
    _ <*> First x = First x 
    Second f <*> Second x = Second (f x)

  instance Arbitrary a => Arbitrary (Sum a b) where
    arbitrary = do
      a <- arbitrary
      b <- arbitrary
      return ???(What should I write here)

  instance (Eq a, Eq b)  => EqProp (Sum a b) where (=-=) = eq 

As you can see, the triple question marks are marked, that I do not know what is going on there?

+4
source share
1 answer

You need to arbitrarily choose between Firstand Second, and then generate a suitable first / second component.

Choosing between a finite number of options can be quickly done with oneOf.

 instance (Arbitrary a, Arbitrary b) => Arbitrary (Sum a b) where
    arbitrary = oneOf [ First <$> arbitrary, Second <$> arbitrary ]

The above is equivalent to the next lower-level instance, which you may find more understandable at first.

 instance (Arbitrary a, Arbitrary b) => Arbitrary (Sum a b) where
    arbitrary = do
       which <- arbitrary   -- a random Bool
       if which
         then do
            a <- arbitrary
            return (First a)
         else do
            b <- arbitrary
            return (Second b)
+8
source

Source: https://habr.com/ru/post/1683254/


All Articles