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?
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With