Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Testing Sum applicative

Tags:

haskell

I want to test the applicative instance on the custom 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 highlighted, that I do not know what comes there?

like image 313
softshipper Avatar asked Jan 29 '23 20:01

softshipper


1 Answers

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

Choosing between a finite amount of choices 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 following lower-level instance, which you might 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)
like image 154
chi Avatar answered Feb 12 '23 20:02

chi